7 my $class = ref($proto) || $proto;
11 my $output = \
${$self->{OUTPUT
}};
12 my $name = \
${$self->{NAME
}};
21 } split(/\n/, `find $path -name \\*.api`);
23 foreach my $file (@files) {
25 $module =~ s/.*?\/([^\/]*?
)\
.api
$/$1/;
26 $self->parse_api_file($file,$module);
34 my $output = \
${$self->{OUTPUT
}};
35 my $allowed_kind = \
%{$self->{ALLOWED_KIND
}};
36 my $allowed_modules = \
%{$self->{ALLOWED_MODULES
}};
37 my $allowed_modules_limited = \
%{$self->{ALLOWED_MODULES_LIMITED
}};
38 my $allowed_modules_unlimited = \
%{$self->{ALLOWED_MODULES_UNLIMITED
}};
39 my $translate_argument = \
%{$self->{TRANSLATE_ARGUMENT
}};
48 $$output->progress("$file");
50 open(IN
, "< $file") || die "$file: $!\n";
53 s/^\s*?(.*?)\s*$/$1/; # remove whitespace at begin and end of line
54 s/^(.*?)\s*#.*$/$1/; # remove comments
55 /^$/ && next; # skip empty lines
62 $$allowed_kind{$kind} = 1;
65 } elsif(/^--extension/) {
68 } elsif(defined($kind)) {
71 if(defined($module)) {
72 if($$allowed_modules_unlimited{$type}) {
73 $$output->write("$file: type ($type) already specificed as an unlimited type\n");
74 } elsif(!$$allowed_modules{$type}{$module}) {
75 $$allowed_modules{$type}{$module} = 1;
76 $$allowed_modules_limited{$type} = 1;
78 $$output->write("$file: type ($type) already specificed\n");
81 $$allowed_modules_unlimited{$type} = 1;
84 $$allowed_modules_limited{$type} = 1;
86 if(defined($$translate_argument{$type}) && $$translate_argument{$type} ne $kind) {
87 $$output->write("$file: type ($type) respecified as different kind ($kind != $$translate_argument{$type})\n");
89 $$translate_argument{$type} = $kind;
92 $$output->write("$file: file must begin with %<type> statement\n");
99 sub get_spec_file_type
{
101 my $class = ref($proto) || $proto;
107 open(IN
, "< $file") || die "$file: $!\n";
110 if(/^type\s*(\w+)/) {
120 sub read_spec_files
{
122 my $class = ref($proto) || $proto;
125 my $win16api = shift;
126 my $win32api = shift;
131 } split(/\n/, `find $path -name \\*.spec`);
133 foreach my $file (@files) {
134 my $type = 'winapi'->get_spec_file_type($file);
135 if($type eq "win16") {
136 $win16api->parse_spec_file($file);
137 } elsif($type eq "win32") {
138 $win32api->parse_spec_file($file);
143 sub parse_spec_file
{
146 my $output = \
${$self->{OUTPUT
}};
147 my $function_arguments = \
%{$self->{FUNCTION_ARGUMENTS
}};
148 my $function_calling_convention = \
%{$self->{FUNCTION_CALLING_CONVENTION
}};
149 my $function_stub = \
%{$self->{FUNCTION_STUB
}};
150 my $function_module = \
%{$self->{FUNCTION_MODULE
}};
159 $$output->progress("$file");
161 open(IN
, "< $file") || die "$file: $!\n";
165 while($lookahead || defined($_ = <IN
>)) {
172 if(/^name\s*(\S*)/) { $module = $1; }
173 if(/^type\s*(\w+)/) { $type = $1; }
174 if(/^\d+|@/) { $header = 0 };
179 if(/^(\d+|@)\s+(pascal|pascal16|stdcall|cdecl|register|interrupt|varargs)\s+(\S+)\s*\(\s*(.*?)\s*\)\s*(\S+)$/) {
180 my $calling_convention = $2;
181 my $external_name = $3;
183 my $internal_name = $5;
187 # FIXME: Internal name existing more than once not handled properly
188 $$function_arguments{$internal_name} = $arguments;
189 $$function_calling_convention{$internal_name} = $calling_convention;
190 if(!$$function_module{$internal_name}) {
191 $$function_module{$internal_name} = "$module";
192 } elsif($$function_module{$internal_name} !~ /$module/) {
193 $$function_module{$internal_name} .= " & $module";
195 } elsif(/^(\d+|@)\s+stub\s+(\S+)$/) {
196 my $external_name = $2;
201 if($type eq "win16") {
202 $internal_name = $external_name . "16";
204 $internal_name = $external_name;
207 # FIXME: Internal name existing more than once not handled properly
208 $$function_stub{$internal_name} = 1;
209 if(!$$function_module{$internal_name}) {
210 $$function_module{$internal_name} = "$module";
211 } elsif($$function_module{$internal_name} !~ /$module/) {
212 $$function_module{$internal_name} .= " & $module";
214 } elsif(/^(\d+|@)\s+(equate|long|word|extern|forward)/) {
217 my $next_line = <IN
>;
218 if($next_line =~ /^\d|@/) {
219 die "$file: $.: syntax error: '$_'\n";
226 if(defined($ordinal)) {
227 if($ordinal ne "@" && $ordinals{$ordinal}) {
228 $$output->write("$file: ordinal redefined: $_\n");
230 $ordinals{$ordinal}++;
238 my $name = \
${$self->{NAME
}};
243 sub is_allowed_kind
{
245 my $allowed_kind = \
%{$self->{ALLOWED_KIND
}};
249 return $$allowed_kind{$kind};
255 sub is_limited_type
{
257 my $allowed_modules_limited = \
%{$self->{ALLOWED_MODULES_LIMITED
}};
261 return $$allowed_modules_limited{$type};
264 sub allowed_type_in_module
{
266 my $allowed_modules = \
%{$self->{ALLOWED_MODULES
}};
267 my $allowed_modules_limited = \
%{$self->{ALLOWED_MODULES_LIMITED
}};
270 my @modules = split(/ \& /, shift);
272 if(!$$allowed_modules_limited{$type}) { return 1; }
274 foreach my $module (@modules) {
275 if($$allowed_modules{$type}{$module}) { return 1; }
281 sub type_used_in_module
{
283 my $used_modules = \
%{$self->{USED_MODULES
}};
286 my @modules = split(/ \& /, shift);
288 foreach my $module (@modules) {
289 $$used_modules{$type}{$module} = 1;
297 my $used_modules = \
%{$self->{USED_MODULES
}};
298 my $allowed_modules = \
%{$self->{ALLOWED_MODULES
}};
301 foreach my $type (sort(keys(%$allowed_modules))) {
302 foreach my $module (sort(keys(%{$$allowed_modules{$type}}))) {
303 if(!$$used_modules{$type}{$module}) {
304 $$not_used{$module}{$type} = 1;
311 sub types_unlimited_used_in_modules
{
314 my $output = \
${$self->{OUTPUT
}};
315 my $used_modules = \
%{$self->{USED_MODULES
}};
316 my $allowed_modules = \
%{$self->{ALLOWED_MODULES
}};
317 my $allowed_modules_unlimited = \
%{$self->{ALLOWED_MODULES_UNLIMITED
}};
320 foreach my $type (sort(keys(%$allowed_modules_unlimited))) {
323 foreach my $module (sort(keys(%{$$used_modules{$type}}))) {
325 push @modules, $module;
328 foreach my $module (@modules) {
329 $$used_types{$type}{$module} = 1;
336 sub translate_argument
{
338 my $translate_argument = \
%{$self->{TRANSLATE_ARGUMENT
}};
340 my $argument = shift;
342 return $$translate_argument{$argument};
345 sub all_declared_types
{
347 my $translate_argument = \
%{$self->{TRANSLATE_ARGUMENT
}};
349 return sort(keys(%$translate_argument));
354 my $type_found = \
%{$self->{TYPE_FOUND
}};
358 $$type_found{$name}++;
363 my $type_found= \
%{$self->{TYPE_FOUND
}};
367 return $$type_found{$name};
372 my $function_calling_convention = \
%{$self->{FUNCTION_CALLING_CONVENTION
}};
374 return sort(keys(%$function_calling_convention));
377 sub all_functions_found
{
379 my $function_found = \
%{$self->{FUNCTION_FOUND
}};
381 return sort(keys(%$function_found));
384 sub function_calling_convention
{
386 my $function_calling_convention = \
%{$self->{FUNCTION_CALLING_CONVENTION
}};
390 return $$function_calling_convention{$name};
395 my $function_calling_convention = \
%{$self->{FUNCTION_CALLING_CONVENTION
}};
399 return $$function_calling_convention{$name};
402 sub is_shared_function
{
404 my $function_shared = \
%{$self->{FUNCTION_SHARED
}};
408 return $$function_shared{$name};
411 sub found_shared_function
{
413 my $function_shared = \
%{$self->{FUNCTION_SHARED
}};
417 $$function_shared{$name} = 1;
420 sub function_arguments
{
422 my $function_arguments = \
%{$self->{FUNCTION_ARGUMENTS
}};
426 return $$function_arguments{$name};
429 sub function_module
{
431 my $function_module = \
%{$self->{FUNCTION_MODULE
}};
435 return $$function_module{$name};
440 my $function_stub = \
%{$self->{FUNCTION_STUB
}};
444 return $$function_stub{$name};
449 my $function_found = \
%{$self->{FUNCTION_FOUND
}};
453 $$function_found{$name}++;
458 my $function_found = \
%{$self->{FUNCTION_FOUND
}};
462 return $$function_found{$name};