Fixed winapi_extract.
[wine] / tools / winapi / winapi.pm
1 #
2 # Copyright 1999, 2000, 2001 Patrik Stridvall
3 #
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.
8 #
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.
13 #
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
17 #
18
19 package winapi;
20
21 use strict;
22
23 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
24 require Exporter;
25
26 @ISA = qw(Exporter);
27 @EXPORT = qw();
28 @EXPORT_OK = qw($win16api $win32api @winapis);
29
30 use vars qw($win16api $win32api @winapis);
31
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);
36
37 my @spec_files16 = $modules->allowed_spec_files16;
38 $win16api = 'winapi'->new("win16", \@spec_files16);
39
40 my @spec_files32 = $modules->allowed_spec_files32;
41 $win32api = 'winapi'->new("win32", \@spec_files32);
42
43 @winapis = ($win16api, $win32api);
44
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))
51     {
52         $win16api->found_shared_internal_function($internal_name);
53         $win32api->found_shared_internal_function($internal_name);
54     }
55 }
56
57 sub new {
58     my $proto = shift;
59     my $class = ref($proto) || $proto;
60     my $self  = {};
61     bless ($self, $class);
62
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}};
67
68     $$name = shift;
69     my $refspec_files = shift;
70
71     foreach my $file (@$refspec_files) {
72         $self->parse_spec_file("$wine_dir/$file");
73     }
74
75     $self->parse_api_file("$$name.api");
76
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";
83         }
84     }
85
86     return $self;
87 }
88
89 sub win16api {
90     return $win16api;
91 }
92
93 sub win32api {
94     return $win32api;
95 }
96
97 sub parse_api_file {
98     my $self = shift;
99
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}};
106
107     my $file = shift;
108
109     my $module;
110     my $kind;
111     my $format;
112     my $extension = 0;
113     my $forbidden = 0;
114
115     $output->lazy_progress("$file");
116
117     open(IN, "< $winapi_dir/$file") || die "$winapi_dir/$file: $!\n";
118     $/ = "\n";
119     while(<IN>) {
120         s/^\s*?(.*?)\s*$/$1/; # remove whitespace at begin and end of line
121         s/^(.*?)\s*#.*$/$1/;  # remove comments
122         /^$/ && next;         # skip empty lines
123
124         if(/^%%(\S+)$/) {
125             $module = $1;
126             $module =~ s/\.dll$//; # FIXME: Kludge
127         } elsif(!$modules->is_allowed_module($module)) {
128             # Nothing
129         } elsif(s/^%(\S+)\s*//) {
130             $kind = $1;
131             $format = undef;
132             $forbidden = 0;
133             $extension = 0;
134
135             $$allowed_kind{$kind} = 1;
136             if(/^--forbidden/) {
137                 $forbidden = 1;
138             } elsif(/^--extension/) {
139                 $extension = 1;
140             } elsif(/^--format=(\".*?\"|\S*)/) {
141                 $format = $1;
142                 $format =~ s/^\"(.*?)\"$/$1/;
143             }
144
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") {
154                     $format = "%lld";
155                 } elsif($kind eq "ptr") {
156                     $format = "%p";
157                 } elsif($kind eq "segptr") {
158                     $format = "%p";
159                 } elsif($kind eq "str") {
160                     $format = "%p|%s";
161                 } elsif($kind eq "wstr") {
162                     $format = "%p|%s";
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";
167                 } else {
168                     $format = "<unknown>";
169                 }
170             }
171         } elsif(defined($kind)) {
172             my $type = $_;
173             if(!$forbidden) {
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;
180                     } else {
181                         $output->write("$file: type ($type) already specificed\n");
182                     }
183                 } else {
184                     $$allowed_modules_unlimited{$type} = 1;
185                 }
186             } else {
187                 $$allowed_modules_limited{$type} = 1;
188             }
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");
191             } else {
192                 $$translate_argument{$type} = $kind;
193             }
194
195             $$type_format{$module}{$type} = $format;
196         } else {
197             $output->write("$file: file must begin with %<type> statement\n");
198             exit 1;
199         }
200     }
201     close(IN);
202 }
203
204 sub parse_spec_file {
205     my $self = shift;
206
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}};
221
222     my $file = shift;
223     $file =~ s%^\./%%;
224
225     my %ordinals;
226     my $module;
227
228     $output->lazy_progress("$file");
229
230     $module = $file;
231     $module =~ s/^.*?([^\/]*)\.spec$/$1/;
232
233     open(IN, "< $file") || die "$file: $!\n";
234     $/ = "\n";
235     my $header = 1;
236     my $lookahead = 0;
237     while($lookahead || defined($_ = <IN>)) {
238         $lookahead = 0;
239         s/^\s*(.*?)\s*$/$1/;
240         s/^(.*?)\s*#.*$/$1/;
241         /^$/ && next;
242
243         if($header)  {
244             if(/^\d+|@/) { $header = 0; $lookahead = 1; }
245             next;
246         }
247
248         my $ordinal;
249         if(/^(\d+|@)\s+
250            (pascal|pascal16|stdcall|cdecl|varargs)\s+
251            ((?:(?:-noimport|-norelay|-i386|-ret64|-register|-interrupt)\s+)*)(\S+)\s*\(\s*(.*?)\s*\)\s*(\S+)$/x)
252         {
253             my $calling_convention = $2;
254             my $flags = $3;
255             my $external_name = $4;
256             my $arguments = $5;
257             my $internal_name = $6;
258
259             $ordinal = $1;
260
261             $flags =~ s/\s+/ /g;
262
263             if($flags =~ /(?:-register|-interrupt)/) {
264                 if($arguments) { $arguments .= " "; }
265                 $arguments .= "ptr";
266             }
267
268             if(!$$function_internal_name{$external_name}) {
269                 $$function_internal_name{$external_name} = $internal_name;
270             } else {
271                 $$function_internal_name{$external_name} .= " & $internal_name";
272             }
273             if(!$$function_external_name{$internal_name}) {
274                 $$function_external_name{$internal_name} = $external_name;
275             } else {
276                 $$function_external_name{$internal_name} .= " & $external_name";
277             }
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;
282             } else {
283                 $$function_internal_ordinal{$internal_name} .= " & $ordinal";
284             }
285             if(!$$function_external_ordinal{$external_name}) {
286                 $$function_external_ordinal{$external_name} = $ordinal;
287             } else {
288                 $$function_external_ordinal{$external_name} .= " & $ordinal";
289             }
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";
294             } else {
295                 $$function_internal_module{$internal_name} .= " & $module";
296             }
297             if(!$$function_external_module{$external_name}) {
298                 $$function_external_module{$external_name} = "$module";
299             } else {
300                 $$function_external_module{$external_name} .= " & $module";
301             }
302
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");
307                     }
308                 } else {
309                     my $name = $external_name;
310
311                     my $name1 = $name;
312                     $name1 =~ s/^Zw/Nt/;
313
314                     my $name2 = $name;
315                     $name2 =~ s/^(?:_|Rtl|k32|K32)//;
316
317                     my $name3 = $name;
318                     $name3 =~ s/^INT_Int[0-9a-f]{2}Handler$/BUILTIN_DefaultIntHandler/;
319
320                     my $name4 = $name;
321                     $name4 =~ s/^(VxDCall)\d$/$1/;
322
323                     # FIXME: This special case is becuase of a very ugly kludge that should be fixed IMHO
324                     my $name5 = $name;
325                     $name5 =~ s/^(.*?16)_(.*?)$/$1_fn$2/;
326
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)/)
329                     {
330                         $output->write("$file: $external_name: internal name ($internal_name) mismatch\n");
331                     }
332                 }
333             }
334         } elsif(/^(\d+|@)\s+stub(?:\s+(?:-noimport|-norelay|-i386|-ret64))?\s+(\S+)$/) {
335             my $external_name = $2;
336
337             $ordinal = $1;
338
339             my $internal_name = $external_name;
340
341             $$function_stub{$module}{$external_name} = 1;
342             if(!$$function_internal_name{$external_name}) {
343                 $$function_internal_name{$external_name} = $internal_name;
344             } else {
345                 $$function_internal_name{$external_name} .= " & $internal_name";
346             }
347             if(!$$function_external_name{$internal_name}) {
348                 $$function_external_name{$internal_name} = $external_name;
349             } else {
350                 $$function_external_name{$internal_name} .= " & $external_name";
351             }
352             if(!$$function_internal_ordinal{$internal_name}) {
353                 $$function_internal_ordinal{$internal_name} = $ordinal;
354             } else {
355                 $$function_internal_ordinal{$internal_name} .= " & $ordinal";
356             }
357             if(!$$function_external_ordinal{$external_name}) {
358                 $$function_external_ordinal{$external_name} = $ordinal;
359             } else {
360                 $$function_external_ordinal{$external_name} .= " & $ordinal";
361             }
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";
366             }
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";
371             }
372         } elsif(/^(\d+|@)\s+forward(?:\s+(?:-noimport|-norelay|-i386|-ret64))?\s+(\S+)\s+(\S+)\.(\S+)$/) {
373             $ordinal = $1;
374
375             my $external_name = $2;
376             my $forward_module = lc($3);
377             my $forward_name = $4;
378
379             $$function_forward{$external_name} = "$module:$forward_module.$forward_name";
380         } elsif(/^(\d+|@)\s+(equate|extern|variable)/) {
381             # ignore
382         } else {
383             my $next_line = <IN>;
384             if(!defined($next_line) || $next_line =~ /^\s*\d|@/) {
385                 die "$file: $.: syntax error: '$_'\n";
386             } else {
387                 $_ .= $next_line;
388                 $lookahead = 1;
389             }
390         }
391
392         if(defined($ordinal)) {
393             if($ordinal ne "@" && $ordinals{$ordinal}) {
394                 $output->write("$file: ordinal redefined: $_\n");
395             }
396             $ordinals{$ordinal}++;
397         }
398     }
399     close(IN);
400
401     $$modules{$module}++;
402
403     $$module_files{$module} = $file;
404 }
405
406 sub name {
407     my $self = shift;
408     my $name = \${$self->{NAME}};
409
410     return $$name;
411 }
412
413 sub is_allowed_kind {
414     my $self = shift;
415     my $allowed_kind = \%{$self->{ALLOWED_KIND}};
416
417     my $kind = shift;
418     if(defined($kind)) {
419         return $$allowed_kind{$kind};
420     } else {
421         return 0;
422     }
423
424 }
425
426 sub allow_kind {
427     my $self = shift;
428     my $allowed_kind = \%{$self->{ALLOWED_KIND}};
429
430     my $kind = shift;
431
432     $$allowed_kind{$kind}++;
433 }
434
435 sub is_limited_type {
436     my $self = shift;
437     my $allowed_modules_limited = \%{$self->{ALLOWED_MODULES_LIMITED}};
438
439     my $type = shift;
440
441     return $$allowed_modules_limited{$type};
442 }
443
444 sub is_allowed_type_in_module {
445     my $self = shift;
446     my $allowed_modules = \%{$self->{ALLOWED_MODULES}};
447     my $allowed_modules_limited = \%{$self->{ALLOWED_MODULES_LIMITED}};
448
449     my $type = shift;
450     my @modules = split(/ \& /, shift);
451
452     if(!$$allowed_modules_limited{$type}) { return 1; }
453
454     foreach my $module (@modules) {
455         if($$allowed_modules{$type}{$module}) { return 1; }
456     }
457
458     return 0;
459 }
460
461 sub allow_type_in_module {
462     my $self = shift;
463     my $allowed_modules = \%{$self->{ALLOWED_MODULES}};
464
465     my $type = shift;
466     my @modules = split(/ \& /, shift);
467
468     foreach my $module (@modules) {
469         $$allowed_modules{$type}{$module}++;
470     }
471 }
472
473 sub type_used_in_module {
474     my $self = shift;
475     my $used_modules = \%{$self->{USED_MODULES}};
476
477     my $type = shift;
478     my @modules = split(/ \& /, shift);
479
480     foreach my $module (@modules) {
481         $$used_modules{$type}{$module} = 1;
482     }
483
484     return ();
485 }
486
487 sub types_not_used {
488     my $self = shift;
489     my $used_modules = \%{$self->{USED_MODULES}};
490     my $allowed_modules = \%{$self->{ALLOWED_MODULES}};
491
492     my $not_used;
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;
497             }
498         }
499     }
500     return $not_used;
501 }
502
503 sub types_unlimited_used_in_modules {
504     my $self = shift;
505
506     my $used_modules = \%{$self->{USED_MODULES}};
507     my $allowed_modules = \%{$self->{ALLOWED_MODULES}};
508     my $allowed_modules_unlimited = \%{$self->{ALLOWED_MODULES_UNLIMITED}};
509
510     my $used_types;
511     foreach my $type (sort(keys(%$allowed_modules_unlimited))) {
512         my $count = 0;
513         my @modules = ();
514         foreach my $module (sort(keys(%{$$used_modules{$type}}))) {
515             $count++;
516             push @modules, $module;
517         }
518         if($count) {
519             foreach my $module (@modules) {
520               $$used_types{$type}{$module} = 1;
521             }
522         }
523     }
524     return $used_types;
525 }
526
527 sub translate_argument {
528     my $self = shift;
529     my $translate_argument = \%{$self->{TRANSLATE_ARGUMENT}};
530
531     my $type = shift;
532
533     return $$translate_argument{$type};
534 }
535
536 sub declare_argument {
537     my $self = shift;
538     my $translate_argument = \%{$self->{TRANSLATE_ARGUMENT}};
539
540     my $type = shift;
541     my $kind = shift;
542
543     $$translate_argument{$type} = $kind;
544 }
545
546 sub all_declared_types {
547     my $self = shift;
548     my $translate_argument = \%{$self->{TRANSLATE_ARGUMENT}};
549
550     return sort(keys(%$translate_argument));
551 }
552
553 sub is_allowed_type_format {
554     my $self = shift;
555     my $type_format = \%{$self->{TYPE_FORMAT}};
556
557     my $module = shift;
558     my $type = shift;
559     my $format = shift;
560
561     my $formats;
562
563     if(defined($module) && defined($type)) {
564         local $_;
565         foreach (split(/ & /, $module)) {
566             if(defined($formats)) {
567                 $formats .= "|";
568             } else {
569                 $formats = "";
570             }
571             if(defined($$type_format{$_}{$type})) {
572                 $formats .= $$type_format{$_}{$type};
573             }
574         }
575     }
576
577     if(defined($formats)) {
578         local $_;
579         foreach (split(/\|/, $formats)) {
580             if($_ eq $format) {
581                 return 1;
582             }
583         }
584     }
585
586     return 0;
587 }
588
589 sub all_modules {
590     my $self = shift;
591     my $modules = \%{$self->{MODULES}};
592
593     return sort(keys(%$modules));
594 }
595
596 sub is_module {
597     my $self = shift;
598     my $modules = \%{$self->{MODULES}};
599
600     my $name = shift;
601
602     return $$modules{$name};
603 }
604
605 sub module_file {
606     my $self = shift;
607
608     my $module = shift;
609
610     my $module_files = \%{$self->{MODULE_FILES}};
611
612     return $$module_files{$module};
613 }
614
615 sub all_internal_functions {
616     my $self = shift;
617     my $function_internal_calling_convention = \%{$self->{FUNCTION_INTERNAL_CALLING_CONVENTION}};
618
619     return sort(keys(%$function_internal_calling_convention));
620 }
621
622 sub all_internal_functions_in_module {
623     my $self = shift;
624     my $function_internal_calling_convention = \%{$self->{FUNCTION_INTERNAL_CALLING_CONVENTION}};
625     my $function_internal_module = \%{$self->{FUNCTION_INTERNAL_MODULE}};
626
627     my $module = shift;
628
629     my @names;
630     foreach my $name (keys(%$function_internal_calling_convention)) {
631         if($$function_internal_module{$name} eq $module) {
632             push @names, $name;
633         }
634     }
635
636     return sort(@names);
637 }
638
639 sub all_external_functions {
640     my $self = shift;
641     my $function_internal_name = \%{$self->{FUNCTION_INTERNAL_NAME}};
642
643     return sort(keys(%$function_internal_name));
644 }
645
646 sub all_external_functions_in_module {
647     my $self = shift;
648     my $function_internal_name = \%{$self->{FUNCTION_INTERNAL_NAME}};
649     my $function_external_module = \%{$self->{FUNCTION_EXTERNAL_MODULE}};
650
651     my $module = shift;
652
653     my @names;
654     foreach my $name (keys(%$function_internal_name)) {
655         if($$function_external_module{$name} eq $module) {
656             push @names, $name;
657         }
658     }
659
660     return sort(@names);
661 }
662
663 sub all_functions_stub {
664     my $self = shift;
665     my $function_stub = \%{$self->{FUNCTION_STUB}};
666     my $modules = \%{$self->{MODULES}};
667
668     my @stubs = ();
669     foreach my $module (keys(%$modules)) {
670         push @stubs, keys(%{$$function_stub{$module}});
671     }
672     return sort(@stubs);
673 }
674
675 sub all_functions_stub_in_module {
676     my $self = shift;
677     my $function_stub = \%{$self->{FUNCTION_STUB}};
678
679     my $module = shift;
680
681     return sort(keys(%{$$function_stub{$module}}));
682 }
683
684 sub function_internal_ordinal {
685     my $self = shift;
686     my $function_internal_ordinal = \%{$self->{FUNCTION_INTERNAL_ORDINAL}};
687
688     my $name = shift;
689
690     return $$function_internal_ordinal{$name};
691 }
692
693 sub function_external_ordinal {
694     my $self = shift;
695     my $function_external_ordinal = \%{$self->{FUNCTION_EXTERNAL_ORDINAL}};
696
697     my $name = shift;
698
699     return $$function_external_ordinal{$name};
700 }
701
702 sub function_internal_calling_convention {
703     my $self = shift;
704     my $function_internal_calling_convention = \%{$self->{FUNCTION_INTERNAL_CALLING_CONVENTION}};
705
706     my $name = shift;
707
708     return $$function_internal_calling_convention{$name};
709 }
710
711 sub function_external_calling_convention {
712     my $self = shift;
713     my $function_external_calling_convention = \%{$self->{FUNCTION_EXTERNAL_CALLING_CONVENTION}};
714
715     my $name = shift;
716
717     return $$function_external_calling_convention{$name};
718 }
719
720 sub function_internal_name {
721     my $self = shift;
722     my $function_internal_name = \%{$self->{FUNCTION_INTERNAL_NAME}};
723
724     my $name = shift;
725
726     return $$function_internal_name{$name};
727 }
728
729 sub function_external_name {
730     my $self = shift;
731     my $function_external_name = \%{$self->{FUNCTION_EXTERNAL_NAME}};
732
733     my $name = shift;
734
735     return $$function_external_name{$name};
736 }
737
738 sub is_function {
739     my $self = shift;
740     my $function_internal_calling_convention = \%{$self->{FUNCTION_INTERNAL_CALLING_CONVENTION}};
741
742     my $name = shift;
743
744     return $$function_internal_calling_convention{$name};
745 }
746
747 sub all_shared_internal_functions {
748     my $self = shift;
749     my $function_shared = \%{$self->{FUNCTION_SHARED}};
750
751     return sort(keys(%$function_shared));
752 }
753
754 sub is_shared_internal_function {
755     my $self = shift;
756     my $function_shared = \%{$self->{FUNCTION_SHARED}};
757
758     my $name = shift;
759
760     return $$function_shared{$name};
761 }
762
763 sub found_shared_internal_function {
764     my $self = shift;
765     my $function_shared = \%{$self->{FUNCTION_SHARED}};
766
767     my $name = shift;
768
769     $$function_shared{$name} = 1;
770 }
771
772 sub function_internal_arguments {
773     my $self = shift;
774     my $function_internal_arguments = \%{$self->{FUNCTION_INTERNAL_ARGUMENTS}};
775
776     my $name = shift;
777
778     return $$function_internal_arguments{$name};
779 }
780
781 sub function_external_arguments {
782     my $self = shift;
783     my $function_external_arguments = \%{$self->{FUNCTION_EXTERNAL_ARGUMENTS}};
784
785     my $name = shift;
786
787     return $$function_external_arguments{$name};
788 }
789
790 sub function_internal_module {
791     my $self = shift;
792     my $function_internal_module = \%{$self->{FUNCTION_INTERNAL_MODULE}};
793
794     my $name = shift;
795
796     return $$function_internal_module{$name};
797 }
798
799 sub function_external_module {
800     my $self = shift;
801     my $function_external_module = \%{$self->{FUNCTION_EXTERNAL_MODULE}};
802
803     my $name = shift;
804
805     return $$function_external_module{$name};
806 }
807
808 sub is_function_stub {
809     my $self = shift;
810     my $function_stub = \%{$self->{FUNCTION_STUB}};
811     my $modules = \%{$self->{MODULES}};
812
813     my $module = shift;
814     my $name = shift;
815
816     foreach my $module (keys(%$modules)) {
817         if($$function_stub{$module}{$name}) {
818             return 1;
819         }
820     }
821
822     return 0;
823 }
824
825 sub is_function_stub_in_module {
826     my $self = shift;
827     my $function_stub = \%{$self->{FUNCTION_STUB}};
828
829     my $module = shift;
830     my $name = shift;
831
832     return $$function_stub{$module}{$name};
833 }
834
835 ########################################################################
836 # class methods
837 #
838
839 sub _get_all_module_internal_ordinal {
840     my $winapi = shift;
841     my $internal_name = shift;
842
843     my @entries = ();
844
845     my @name = (); {
846         my $name = $winapi->function_external_name($internal_name);
847         if(defined($name)) {
848             @name = split(/ & /, $name);
849         }
850     }
851
852     my @module = (); {
853         my $module = $winapi->function_internal_module($internal_name);
854         if(defined($module)) {
855             @module = split(/ & /, $module);
856         }
857     }
858
859     my @ordinal = (); {
860         my $ordinal = $winapi->function_internal_ordinal($internal_name);
861         if(defined($ordinal)) {
862             @ordinal = split(/ & /, $ordinal);
863         }
864     }
865
866     my $name;
867     my $module;
868     my $ordinal;
869     while(defined($name = shift @name) &&
870           defined($module = shift @module) &&
871           defined($ordinal = shift @ordinal))
872     {
873         push @entries, [$name, $module, $ordinal];
874     }
875
876     return @entries;
877 }
878
879 sub get_all_module_internal_ordinal16 {
880     return _get_all_module_internal_ordinal($win16api, @_);
881 }
882
883 sub get_all_module_internal_ordinal32 {
884     return _get_all_module_internal_ordinal($win32api, @_);
885 }
886
887 sub get_all_module_internal_ordinal {
888     my @entries = ();
889     foreach my $winapi (@winapis) {
890         push @entries, _get_all_module_internal_ordinal($winapi, @_);
891     }
892
893     return @entries;
894 }
895
896 sub _get_all_module_external_ordinal {
897     my $winapi = shift;
898     my $external_name = shift;
899
900     my @entries = ();
901
902     my @name = (); {
903         my $name = $winapi->function_internal_name($external_name);
904         if(defined($name)) {
905             @name = split(/ & /, $name);
906         }
907     }
908
909     my @module = (); {
910         my $module = $winapi->function_external_module($external_name);
911         if(defined($module)) {
912             @module = split(/ & /, $module);
913         }
914     }
915
916     my @ordinal = (); {
917         my $ordinal = $winapi->function_external_ordinal($external_name);
918         if(defined($ordinal)) {
919             @ordinal = split(/ & /, $ordinal);
920         }
921     }
922
923     my $name;
924     my $module;
925     my $ordinal;
926     while(defined($name = shift @name) &&
927           defined($module = shift @module) &&
928           defined($ordinal = shift @ordinal))
929     {
930         push @entries, [$name, $module, $ordinal];
931     }
932
933     return @entries;
934 }
935
936 sub get_all_module_external_ordinal16 {
937     return _get_all_module_external_ordinal($win16api, @_);
938 }
939
940 sub get_all_module_external_ordinal32 {
941     return _get_all_module_external_ordinal($win32api, @_);
942 }
943
944 sub get_all_module_external_ordinal {
945     my @entries = ();
946     foreach my $winapi (@winapis) {
947         push @entries, _get_all_module_external_ordinal($winapi, @_);
948     }
949
950     return @entries;
951 }
952
953 1;