[inseparable changes from patch from perl5.003_24 to perl5.003_25]
[p5sagit/p5-mst-13.2.git] / lib / ExtUtils / xsubpp
CommitLineData
2304df62 1#!./miniperl
75f92628 2
3=head1 NAME
4
5xsubpp - compiler to convert Perl XS code into C code
6
7=head1 SYNOPSIS
8
8fc38fda 9B<xsubpp> [B<-v>] [B<-C++>] [B<-except>] [B<-s pattern>] [B<-prototypes>] [B<-noversioncheck>] [B<-typemap typemap>]... file.xs
75f92628 10
11=head1 DESCRIPTION
12
13I<xsubpp> will compile XS code into C code by embedding the constructs
14necessary to let C functions manipulate Perl values and creates the glue
15necessary to let Perl access those functions. The compiler uses typemaps to
16determine how to map C function parameters and variables to Perl values.
17
18The compiler will search for typemap files called I<typemap>. It will use
19the following search path to find default typemaps, with the rightmost
20typemap taking precedence.
21
22 ../../../typemap:../../typemap:../typemap:typemap
23
24=head1 OPTIONS
25
26=over 5
27
28=item B<-C++>
29
30Adds ``extern "C"'' to the C code.
31
32
33=item B<-except>
34
35Adds exception handling stubs to the C code.
36
37=item B<-typemap typemap>
38
39Indicates that a user-supplied typemap should take precedence over the
40default typemaps. This option may be used multiple times, with the last
41typemap having the highest precedence.
42
8e07c86e 43=item B<-v>
44
45Prints the I<xsubpp> version number to standard output, then exits.
46
8fc38fda 47=item B<-prototypes>
382b8d97 48
8fc38fda 49By default I<xsubpp> will not automatically generate prototype code for
50all xsubs. This flag will enable prototypes.
51
52=item B<-noversioncheck>
53
54Disables the run time test that determines if the object file (derived
55from the C<.xs> file) and the C<.pm> files have the same version
56number.
382b8d97 57
75f92628 58=back
59
60=head1 ENVIRONMENT
61
62No environment variables are used.
63
64=head1 AUTHOR
65
66Larry Wall
67
f06db76b 68=head1 MODIFICATION HISTORY
69
8e07c86e 70See the file F<changes.pod>.
e50aee73 71
75f92628 72=head1 SEE ALSO
73
a5dbbe28 74perl(1), perlxs(1), perlxstut(1), perlxs(1)
75f92628 75
76=cut
93a17b20 77
382b8d97 78require 5.002;
774d564b 79use Cwd;
4230ab3f 80use vars '$cplusplus';
382b8d97 81
774d564b 82# Global Constants
83$XSUBPP_version = "1.94001";
84$Is_VMS = $^O eq 'VMS';
85
8fc38fda 86sub Q ;
87
c07a80fd 88$FH = 'File0000' ;
8fc38fda 89
90$usage = "Usage: xsubpp [-v] [-C++] [-except] [-prototypes] [-noversioncheck] [-s pattern] [-typemap typemap]... file.xs\n";
f06db76b 91
382b8d97 92$proto_re = "[" . quotemeta('\$%&*@;') . "]" ;
93a17b20 93
8e07c86e 94$except = "";
8fc38fda 95$WantPrototypes = -1 ;
96$WantVersionChk = 1 ;
97$ProtoUsed = 0 ;
8e07c86e 98SWITCH: while (@ARGV and $ARGV[0] =~ /^-./) {
93a17b20 99 $flag = shift @ARGV;
e50aee73 100 $flag =~ s/^-// ;
ff68c719 101 $spat = quotemeta shift, next SWITCH if $flag eq 's';
8990e307 102 $cplusplus = 1, next SWITCH if $flag eq 'C++';
382b8d97 103 $WantPrototypes = 0, next SWITCH if $flag eq 'noprototypes';
104 $WantPrototypes = 1, next SWITCH if $flag eq 'prototypes';
8fc38fda 105 $WantVersionChk = 0, next SWITCH if $flag eq 'noversioncheck';
106 $WantVersionChk = 1, next SWITCH if $flag eq 'versioncheck';
8e07c86e 107 $except = " TRY", next SWITCH if $flag eq 'except';
8990e307 108 push(@tm,shift), next SWITCH if $flag eq 'typemap';
8e07c86e 109 (print "xsubpp version $XSUBPP_version\n"), exit
110 if $flag eq 'v';
93a17b20 111 die $usage;
112}
8fc38fda 113if ($WantPrototypes == -1)
114 { $WantPrototypes = 0}
115else
116 { $ProtoUsed = 1 }
117
118
8990e307 119@ARGV == 1 or die $usage;
c2960299 120($dir, $filename) = $ARGV[0] =~ m#(.*)/(.*)#
121 or ($dir, $filename) = $ARGV[0] =~ m#(.*[>\]])(.*)#
8990e307 122 or ($dir, $filename) = ('.', $ARGV[0]);
123chdir($dir);
774d564b 124$pwd = cwd();
8fc38fda 125
126++ $IncludedFiles{$ARGV[0]} ;
93a17b20 127
4230ab3f 128my(@XSStack) = ({type => 'none'}); # Stack of conditionals and INCLUDEs
129my($XSS_work_idx, $cpp_next_tmp) = (0, "XSubPPtmpAAAA");
130
f06db76b 131sub TrimWhitespace
132{
133 $_[0] =~ s/^\s+|\s+$//go ;
134}
135
136sub TidyType
137{
138 local ($_) = @_ ;
139
140 # rationalise any '*' by joining them into bunches and removing whitespace
141 s#\s*(\*+)\s*#$1#g;
e50aee73 142 s#(\*+)# $1 #g ;
f06db76b 143
144 # change multiple whitespace into a single space
145 s/\s+/ /g ;
146
147 # trim leading & trailing whitespace
148 TrimWhitespace($_) ;
149
150 $_ ;
151}
152
93a17b20 153$typemap = shift @ARGV;
8990e307 154foreach $typemap (@tm) {
155 die "Can't find $typemap in $pwd\n" unless -r $typemap;
93a17b20 156}
748a9306 157unshift @tm, qw(../../../../lib/ExtUtils/typemap ../../../lib/ExtUtils/typemap
158 ../../lib/ExtUtils/typemap ../../../typemap ../../typemap
159 ../typemap typemap);
8990e307 160foreach $typemap (@tm) {
f06db76b 161 next unless -e $typemap ;
162 # skip directories, binary files etc.
163 warn("Warning: ignoring non-text typemap file '$typemap'\n"), next
164 unless -T $typemap ;
165 open(TYPEMAP, $typemap)
166 or warn ("Warning: could not open typemap file '$typemap': $!\n"), next;
e50aee73 167 $mode = 'Typemap';
c2960299 168 $junk = "" ;
8990e307 169 $current = \$junk;
170 while (<TYPEMAP>) {
e50aee73 171 next if /^\s*#/;
e1f0c0aa 172 my $line_no = $. + 1;
8e07c86e 173 if (/^INPUT\s*$/) { $mode = 'Input'; $current = \$junk; next; }
174 if (/^OUTPUT\s*$/) { $mode = 'Output'; $current = \$junk; next; }
175 if (/^TYPEMAP\s*$/) { $mode = 'Typemap'; $current = \$junk; next; }
e50aee73 176 if ($mode eq 'Typemap') {
177 chomp;
f06db76b 178 my $line = $_ ;
179 TrimWhitespace($_) ;
180 # skip blank lines and comment lines
181 next if /^$/ or /^#/ ;
382b8d97 182 my($type,$kind, $proto) = /^\s*(.*?\S)\s+(\S+)\s*($proto_re*)\s*$/ or
183 warn("Warning: File '$typemap' Line $. '$line' TYPEMAP entry needs 2 or 3 columns\n"), next;
184 $type = TidyType($type) ;
185 $type_kind{$type} = $kind ;
186 # prototype defaults to '$'
93d3b392 187 $proto = "\$" unless $proto ;
382b8d97 188 warn("Warning: File '$typemap' Line $. '$line' Invalid prototype '$proto'\n")
189 unless ValidProtoString($proto) ;
190 $proto_letter{$type} = C_string($proto) ;
8e07c86e 191 }
192 elsif (/^\s/) {
193 $$current .= $_;
463ee0b2 194 }
e50aee73 195 elsif ($mode eq 'Input') {
8e07c86e 196 s/\s+$//;
197 $input_expr{$_} = '';
198 $current = \$input_expr{$_};
93a17b20 199 }
8990e307 200 else {
8e07c86e 201 s/\s+$//;
202 $output_expr{$_} = '';
203 $current = \$output_expr{$_};
93a17b20 204 }
8990e307 205 }
206 close(TYPEMAP);
207}
93a17b20 208
8990e307 209foreach $key (keys %input_expr) {
210 $input_expr{$key} =~ s/\n+$//;
211}
93a17b20 212
8e07c86e 213$END = "!End!\n\n"; # "impossible" keyword (multiple newline)
214
215# Match an XS keyword
382b8d97 216$BLOCK_re= '\s*(' . join('|', qw(
217 REQUIRE BOOT CASE PREINIT INPUT INIT CODE PPCODE OUTPUT
8fc38fda 218 CLEANUP ALIAS PROTOTYPES PROTOTYPE VERSIONCHECK INCLUDE
db3b9414 219 SCOPE
382b8d97 220 )) . "|$END)\\s*:";
8e07c86e 221
222# Input: ($_, @line) == unparsed input.
223# Output: ($_, @line) == (rest of line, following lines).
224# Return: the matched keyword if found, otherwise 0
225sub check_keyword {
226 $_ = shift(@line) while !/\S/ && @line;
227 s/^(\s*)($_[0])\s*:\s*(?:#.*)?/$1/s && $2;
228}
229
230
231sub print_section {
e1f0c0aa 232 my $count = 0;
8e07c86e 233 $_ = shift(@line) while !/\S/ && @line;
234 for (; defined($_) && !/^$BLOCK_re/o; $_ = shift(@line)) {
e1f0c0aa 235 print line_directive() unless ($count++);
8e07c86e 236 print "$_\n";
237 }
238}
239
8fc38fda 240sub process_keyword($)
241{
242 my($pattern) = @_ ;
243 my $kwd ;
244
245 &{"${kwd}_handler"}()
246 while $kwd = check_keyword($pattern) ;
e1f0c0aa 247 print line_directive();
8fc38fda 248}
249
8e07c86e 250sub CASE_handler {
251 blurt ("Error: `CASE:' after unconditional `CASE:'")
252 if $condnum && $cond eq '';
253 $cond = $_;
254 TrimWhitespace($cond);
255 print " ", ($condnum++ ? " else" : ""), ($cond ? " if ($cond)\n" : "\n");
256 $_ = '' ;
257}
258
259sub INPUT_handler {
260 for (; !/^$BLOCK_re/o; $_ = shift(@line)) {
261 last if /^\s*NOT_IMPLEMENTED_YET/;
262 next unless /\S/; # skip blank lines
263
264 TrimWhitespace($_) ;
265 my $line = $_ ;
266
267 # remove trailing semicolon if no initialisation
268 s/\s*;$//g unless /=/ ;
269
270 # check for optional initialisation code
271 my $var_init = '' ;
272 $var_init = $1 if s/\s*(=.*)$//s ;
273 $var_init =~ s/"/\\"/g;
274
275 s/\s+/ /g;
276 my ($var_type, $var_addr, $var_name) = /^(.*?[^& ]) *(\&?) *\b(\w+)$/s
277 or blurt("Error: invalid argument declaration '$line'"), next;
278
279 # Check for duplicate definitions
280 blurt ("Error: duplicate definition of argument '$var_name' ignored"), next
281 if $arg_list{$var_name} ++ ;
282
283 $thisdone |= $var_name eq "THIS";
284 $retvaldone |= $var_name eq "RETVAL";
285 $var_types{$var_name} = $var_type;
286 print "\t" . &map_type($var_type);
287 $var_num = $args_match{$var_name};
382b8d97 288
8fc38fda 289 $proto_arg[$var_num] = ProtoString($var_type)
290 if $var_num ;
8e07c86e 291 if ($var_addr) {
292 $var_addr{$var_name} = 1;
293 $func_args =~ s/\b($var_name)\b/&$1/;
294 }
295 if ($var_init =~ /^=\s*NO_INIT\s*;?\s*$/) {
296 print "\t$var_name;\n";
297 } elsif ($var_init =~ /\S/) {
298 &output_init($var_type, $var_num, "$var_name $var_init");
299 } elsif ($var_num) {
300 # generate initialization code
301 &generate_init($var_type, $var_num, $var_name);
302 } else {
303 print ";\n";
304 }
305 }
306}
307
308sub OUTPUT_handler {
309 for (; !/^$BLOCK_re/o; $_ = shift(@line)) {
310 next unless /\S/;
311 my ($outarg, $outcode) = /^\s*(\S+)\s*(.*?)\s*$/s ;
312 blurt ("Error: duplicate OUTPUT argument '$outarg' ignored"), next
313 if $outargs{$outarg} ++ ;
314 if (!$gotRETVAL and $outarg eq 'RETVAL') {
315 # deal with RETVAL last
316 $RETVAL_code = $outcode ;
317 $gotRETVAL = 1 ;
318 next ;
319 }
320 blurt ("Error: OUTPUT $outarg not an argument"), next
321 unless defined($args_match{$outarg});
322 blurt("Error: No input definition for OUTPUT argument '$outarg' - ignored"), next
323 unless defined $var_types{$outarg} ;
e1f0c0aa 324 print line_directive();
8e07c86e 325 if ($outcode) {
326 print "\t$outcode\n";
327 } else {
328 $var_num = $args_match{$outarg};
329 &generate_output($var_types{$outarg}, $var_num, $outarg);
330 }
331 }
332}
333
8fc38fda 334sub CLEANUP_handler() { print_section() }
335sub PREINIT_handler() { print_section() }
336sub INIT_handler() { print_section() }
337
8e07c86e 338sub GetAliases
339{
340 my ($line) = @_ ;
341 my ($orig) = $line ;
342 my ($alias) ;
343 my ($value) ;
344
345 # Parse alias definitions
346 # format is
347 # alias = value alias = value ...
348
349 while ($line =~ s/^\s*([\w:]+)\s*=\s*(\w+)\s*//) {
350 $alias = $1 ;
351 $orig_alias = $alias ;
352 $value = $2 ;
353
354 # check for optional package definition in the alias
355 $alias = $Packprefix . $alias if $alias !~ /::/ ;
356
357 # check for duplicate alias name & duplicate value
358 Warn("Warning: Ignoring duplicate alias '$orig_alias'")
4230ab3f 359 if defined $XsubAliases{$alias} ;
8e07c86e 360
4230ab3f 361 Warn("Warning: Aliases '$orig_alias' and '$XsubAliasValues{$value}' have identical values")
362 if $XsubAliasValues{$value} ;
8e07c86e 363
4230ab3f 364 $XsubAliases = 1;
365 $XsubAliases{$alias} = $value ;
366 $XsubAliasValues{$value} = $orig_alias ;
8e07c86e 367 }
368
369 blurt("Error: Cannot parse ALIAS definitions from '$orig'")
370 if $line ;
371}
372
382b8d97 373sub ALIAS_handler ()
8e07c86e 374{
375 for (; !/^$BLOCK_re/o; $_ = shift(@line)) {
376 next unless /\S/;
377 TrimWhitespace($_) ;
378 GetAliases($_) if $_ ;
379 }
380}
381
382b8d97 382sub REQUIRE_handler ()
8e07c86e 383{
384 # the rest of the current line should contain a version number
385 my ($Ver) = $_ ;
386
387 TrimWhitespace($Ver) ;
388
389 death ("Error: REQUIRE expects a version number")
390 unless $Ver ;
391
392 # check that the version number is of the form n.n
393 death ("Error: REQUIRE: expected a number, got '$Ver'")
394 unless $Ver =~ /^\d+(\.\d*)?/ ;
395
396 death ("Error: xsubpp $Ver (or better) required--this is only $XSUBPP_version.")
397 unless $XSUBPP_version >= $Ver ;
398}
399
8fc38fda 400sub VERSIONCHECK_handler ()
401{
402 # the rest of the current line should contain either ENABLE or
403 # DISABLE
404
405 TrimWhitespace($_) ;
406
407 # check for ENABLE/DISABLE
408 death ("Error: VERSIONCHECK: ENABLE/DISABLE")
409 unless /^(ENABLE|DISABLE)/i ;
410
411 $WantVersionChk = 1 if $1 eq 'ENABLE' ;
412 $WantVersionChk = 0 if $1 eq 'DISABLE' ;
413
414}
415
382b8d97 416sub PROTOTYPE_handler ()
417{
7d41bd0a 418 my $specified ;
419
c07a80fd 420 death("Error: Only 1 PROTOTYPE definition allowed per xsub")
421 if $proto_in_this_xsub ++ ;
422
382b8d97 423 for (; !/^$BLOCK_re/o; $_ = shift(@line)) {
424 next unless /\S/;
7d41bd0a 425 $specified = 1 ;
382b8d97 426 TrimWhitespace($_) ;
427 if ($_ eq 'DISABLE') {
428 $ProtoThisXSUB = 0
429 }
430 elsif ($_ eq 'ENABLE') {
431 $ProtoThisXSUB = 1
432 }
433 else {
434 # remove any whitespace
435 s/\s+//g ;
436 death("Error: Invalid prototype '$_'")
437 unless ValidProtoString($_) ;
438 $ProtoThisXSUB = C_string($_) ;
439 }
440 }
c07a80fd 441
7d41bd0a 442 # If no prototype specified, then assume empty prototype ""
443 $ProtoThisXSUB = 2 unless $specified ;
444
8fc38fda 445 $ProtoUsed = 1 ;
c07a80fd 446
382b8d97 447}
448
db3b9414 449sub SCOPE_handler ()
450{
451 death("Error: Only 1 SCOPE declaration allowed per xsub")
452 if $scope_in_this_xsub ++ ;
453
454 for (; !/^$BLOCK_re/o; $_ = shift(@line)) {
455 next unless /\S/;
456 TrimWhitespace($_) ;
457 if ($_ =~ /^DISABLE/i) {
458 $ScopeThisXSUB = 0
459 }
460 elsif ($_ =~ /^ENABLE/i) {
461 $ScopeThisXSUB = 1
462 }
463 }
464
465}
466
382b8d97 467sub PROTOTYPES_handler ()
468{
469 # the rest of the current line should contain either ENABLE or
470 # DISABLE
471
472 TrimWhitespace($_) ;
473
474 # check for ENABLE/DISABLE
475 death ("Error: PROTOTYPES: ENABLE/DISABLE")
476 unless /^(ENABLE|DISABLE)/i ;
477
478 $WantPrototypes = 1 if $1 eq 'ENABLE' ;
479 $WantPrototypes = 0 if $1 eq 'DISABLE' ;
8fc38fda 480 $ProtoUsed = 1 ;
382b8d97 481
482}
483
8fc38fda 484sub INCLUDE_handler ()
485{
486 # the rest of the current line should contain a valid filename
487
488 TrimWhitespace($_) ;
489
8fc38fda 490 death("INCLUDE: filename missing")
491 unless $_ ;
492
493 death("INCLUDE: output pipe is illegal")
494 if /^\s*\|/ ;
495
496 # simple minded recursion detector
497 death("INCLUDE loop detected")
498 if $IncludedFiles{$_} ;
499
500 ++ $IncludedFiles{$_} unless /\|\s*$/ ;
501
502 # Save the current file context.
4230ab3f 503 push(@XSStack, {
504 type => 'file',
8fc38fda 505 LastLine => $lastline,
506 LastLineNo => $lastline_no,
507 Line => \@line,
508 LineNo => \@line_no,
509 Filename => $filename,
c07a80fd 510 Handle => $FH,
8fc38fda 511 }) ;
512
c07a80fd 513 ++ $FH ;
8fc38fda 514
515 # open the new file
c07a80fd 516 open ($FH, "$_") or death("Cannot open '$_': $!") ;
8fc38fda 517
518 print Q<<"EOF" ;
519#
520#/* INCLUDE: Including '$_' from '$filename' */
521#
522EOF
523
8fc38fda 524 $filename = $_ ;
525
c07a80fd 526 # Prime the pump by reading the first
527 # non-blank line
528
529 # skip leading blank lines
530 while (<$FH>) {
531 last unless /^\s*$/ ;
532 }
533
534 $lastline = $_ ;
8fc38fda 535 $lastline_no = $. ;
536
537}
538
539sub PopFile()
540{
4230ab3f 541 return 0 unless $XSStack[-1]{type} eq 'file' ;
542
543 my $data = pop @XSStack ;
8fc38fda 544 my $ThisFile = $filename ;
545 my $isPipe = ($filename =~ /\|\s*$/) ;
546
547 -- $IncludedFiles{$filename}
548 unless $isPipe ;
549
c07a80fd 550 close $FH ;
8fc38fda 551
c07a80fd 552 $FH = $data->{Handle} ;
8fc38fda 553 $filename = $data->{Filename} ;
554 $lastline = $data->{LastLine} ;
555 $lastline_no = $data->{LastLineNo} ;
556 @line = @{ $data->{Line} } ;
557 @line_no = @{ $data->{LineNo} } ;
4230ab3f 558
8fc38fda 559 if ($isPipe and $? ) {
560 -- $lastline_no ;
561 print STDERR "Error reading from pipe '$ThisFile': $! in $filename, line $lastline_no\n" ;
562 exit 1 ;
563 }
564
565 print Q<<"EOF" ;
566#
567#/* INCLUDE: Returning to '$filename' from '$ThisFile' */
568#
569EOF
570
571 return 1 ;
572}
573
382b8d97 574sub ValidProtoString ($)
575{
576 my($string) = @_ ;
577
578 if ( $string =~ /^$proto_re+$/ ) {
579 return $string ;
580 }
581
582 return 0 ;
583}
584
585sub C_string ($)
586{
587 my($string) = @_ ;
588
589 $string =~ s[\\][\\\\]g ;
590 $string ;
591}
592
593sub ProtoString ($)
594{
595 my ($type) = @_ ;
596
93d3b392 597 $proto_letter{$type} or "\$" ;
382b8d97 598}
599
8e07c86e 600sub check_cpp {
601 my @cpp = grep(/^\#\s*(?:if|e\w+)/, @line);
602 if (@cpp) {
603 my ($cpp, $cpplevel);
604 for $cpp (@cpp) {
605 if ($cpp =~ /^\#\s*if/) {
606 $cpplevel++;
607 } elsif (!$cpplevel) {
608 Warn("Warning: #else/elif/endif without #if in this function");
4230ab3f 609 print STDERR " (precede it with a blank line if the matching #if is outside the function)\n"
610 if $XSStack[-1]{type} eq 'if';
8e07c86e 611 return;
612 } elsif ($cpp =~ /^\#\s*endif/) {
613 $cpplevel--;
614 }
615 }
616 Warn("Warning: #if without #endif in this function") if $cpplevel;
617 }
618}
619
620
8990e307 621sub Q {
e50aee73 622 my($text) = @_;
4633a7c4 623 $text =~ s/^#//gm;
2304df62 624 $text =~ s/\[\[/{/g;
625 $text =~ s/\]\]/}/g;
8990e307 626 $text;
93a17b20 627}
628
c07a80fd 629open($FH, $filename) or die "cannot open $filename: $!\n";
c2960299 630
f06db76b 631# Identify the version of xsubpp used
f06db76b 632print <<EOM ;
e50aee73 633/*
634 * This file was generated automatically by xsubpp version $XSUBPP_version from the
93d3b392 635 * contents of $filename. Do not edit this file, edit $filename instead.
e50aee73 636 *
637 * ANY CHANGES MADE HERE WILL BE LOST!
f06db76b 638 *
639 */
e50aee73 640
f06db76b 641EOM
e1f0c0aa 642print "#line 1 \"$filename\"\n";
f06db76b 643
c07a80fd 644while (<$FH>) {
e50aee73 645 last if ($Module, $Package, $Prefix) =
646 /^MODULE\s*=\s*([\w:]+)(?:\s+PACKAGE\s*=\s*([\w:]+))?(?:\s+PREFIX\s*=\s*(\S+))?\s*$/;
a0d0e21e 647 print $_;
93a17b20 648}
e50aee73 649&Exit unless defined $_;
650
8fc38fda 651$lastline = $_;
652$lastline_no = $.;
93a17b20 653
c07a80fd 654# Read next xsub into @line from ($lastline, <$FH>).
2304df62 655sub fetch_para {
656 # parse paragraph
4230ab3f 657 death ("Error: Unterminated `#if/#ifdef/#ifndef'")
658 if !defined $lastline && $XSStack[-1]{type} eq 'if';
2304df62 659 @line = ();
c2960299 660 @line_no = () ;
4230ab3f 661 return PopFile() if !defined $lastline;
e50aee73 662
663 if ($lastline =~
664 /^MODULE\s*=\s*([\w:]+)(?:\s+PACKAGE\s*=\s*([\w:]+))?(?:\s+PREFIX\s*=\s*(\S+))?\s*$/) {
665 $Module = $1;
8e07c86e 666 $Package = defined($2) ? $2 : ''; # keep -w happy
667 $Prefix = defined($3) ? $3 : ''; # keep -w happy
ff68c719 668 $Prefix = quotemeta $Prefix ;
e50aee73 669 ($Module_cname = $Module) =~ s/\W/_/g;
8e07c86e 670 ($Packid = $Package) =~ tr/:/_/;
e50aee73 671 $Packprefix = $Package;
8e07c86e 672 $Packprefix .= "::" if $Packprefix ne "";
2304df62 673 $lastline = "";
e50aee73 674 }
675
676 for(;;) {
677 if ($lastline !~ /^\s*#/ ||
4230ab3f 678 # CPP directives:
679 # ANSI: if ifdef ifndef elif else endif define undef
680 # line error pragma
681 # gcc: warning include_next
682 # obj-c: import
683 # others: ident (gcc notes that some cpps have this one)
684 $lastline =~ /^#[ \t]*(?:(?:if|ifn?def|elif|else|endif|define|undef|pragma|error|warning|line\s+\d+|ident)\b|(?:include(?:_next)?|import)\s*["<].*[>"])/) {
e50aee73 685 last if $lastline =~ /^\S/ && @line && $line[-1] eq "";
686 push(@line, $lastline);
687 push(@line_no, $lastline_no) ;
93a17b20 688 }
e50aee73 689
690 # Read next line and continuation lines
c07a80fd 691 last unless defined($lastline = <$FH>);
e50aee73 692 $lastline_no = $.;
693 my $tmp_line;
694 $lastline .= $tmp_line
c07a80fd 695 while ($lastline =~ /\\$/ && defined($tmp_line = <$FH>));
e50aee73 696
8e07c86e 697 chomp $lastline;
e50aee73 698 $lastline =~ s/^\s+$//;
2304df62 699 }
e50aee73 700 pop(@line), pop(@line_no) while @line && $line[-1] eq "";
e50aee73 701 1;
2304df62 702}
93a17b20 703
c2960299 704PARAGRAPH:
8e07c86e 705while (fetch_para()) {
e50aee73 706 # Print initial preprocessor statements and blank lines
4230ab3f 707 while (@line && $line[0] !~ /^[^\#]/) {
708 my $line = shift(@line);
709 print $line, "\n";
710 next unless $line =~ /^\#\s*((if)(?:n?def)?|elsif|else|endif)\b/;
711 my $statement = $+;
712 if ($statement eq 'if') {
713 $XSS_work_idx = @XSStack;
714 push(@XSStack, {type => 'if'});
715 } else {
716 death ("Error: `$statement' with no matching `if'")
717 if $XSStack[-1]{type} ne 'if';
718 if ($XSStack[-1]{varname}) {
719 push(@InitFileCode, "#endif\n");
720 push(@BootCode, "#endif");
721 }
722
723 my(@fns) = keys %{$XSStack[-1]{functions}};
724 if ($statement ne 'endif') {
725 # Hide the functions defined in other #if branches, and reset.
726 @{$XSStack[-1]{other_functions}}{@fns} = (1) x @fns;
727 @{$XSStack[-1]}{qw(varname functions)} = ('', {});
728 } else {
729 my($tmp) = pop(@XSStack);
730 0 while (--$XSS_work_idx
731 && $XSStack[$XSS_work_idx]{type} ne 'if');
732 # Keep all new defined functions
733 push(@fns, keys %{$tmp->{other_functions}});
734 @{$XSStack[$XSS_work_idx]{functions}}{@fns} = (1) x @fns;
735 }
736 }
737 }
e50aee73 738
739 next PARAGRAPH unless @line;
740
4230ab3f 741 if ($XSS_work_idx && !$XSStack[$XSS_work_idx]{varname}) {
742 # We are inside an #if, but have not yet #defined its xsubpp variable.
743 print "#define $cpp_next_tmp 1\n\n";
744 push(@InitFileCode, "#if $cpp_next_tmp\n");
745 push(@BootCode, "#if $cpp_next_tmp");
746 $XSStack[$XSS_work_idx]{varname} = $cpp_next_tmp++;
747 }
748
55497cff 749 death ("Code is not inside a function"
750 ." (maybe last function was ended by a blank line "
751 ." followed by a a statement on column one?)")
e50aee73 752 if $line[0] =~ /^\s/;
753
2304df62 754 # initialize info arrays
755 undef(%args_match);
756 undef(%var_types);
757 undef(%var_addr);
758 undef(%defaults);
759 undef($class);
760 undef($static);
761 undef($elipsis);
f06db76b 762 undef($wantRETVAL) ;
763 undef(%arg_list) ;
382b8d97 764 undef(@proto_arg) ;
c07a80fd 765 undef($proto_in_this_xsub) ;
db3b9414 766 undef($scope_in_this_xsub) ;
382b8d97 767 $ProtoThisXSUB = $WantPrototypes ;
db3b9414 768 $ScopeThisXSUB = 0;
2304df62 769
8e07c86e 770 $_ = shift(@line);
8fc38fda 771 while ($kwd = check_keyword("REQUIRE|PROTOTYPES|VERSIONCHECK|INCLUDE")) {
772 &{"${kwd}_handler"}() ;
8e07c86e 773 next PARAGRAPH unless @line ;
774 $_ = shift(@line);
775 }
c2960299 776
8e07c86e 777 if (check_keyword("BOOT")) {
778 &check_cpp;
e1f0c0aa 779 push (@BootCode, $_, line_directive(), @line, "") ;
c2960299 780 next PARAGRAPH ;
a0d0e21e 781 }
c2960299 782
8e07c86e 783
784 # extract return type, function name and arguments
785 my($ret_type) = TidyType($_);
786
c2960299 787 # a function definition needs at least 2 lines
788 blurt ("Error: Function definition too short '$ret_type'"), next PARAGRAPH
789 unless @line ;
790
8e07c86e 791 $static = 1 if $ret_type =~ s/^static\s+//;
792
2304df62 793 $func_header = shift(@line);
c2960299 794 blurt ("Error: Cannot parse function definition from '$func_header'"), next PARAGRAPH
8e07c86e 795 unless $func_header =~ /^(?:([\w:]*)::)?(\w+)\s*\(\s*(.*?)\s*\)\s*$/s;
c2960299 796
8e07c86e 797 ($class, $func_name, $orig_args) = ($1, $2, $3) ;
2304df62 798 ($pname = $func_name) =~ s/^($Prefix)?/$Packprefix/;
ff68c719 799 ($clean_func_name = $func_name) =~ s/^$Prefix//;
800 $Full_func_name = "${Packid}_$clean_func_name";
c2960299 801
802 # Check for duplicate function definition
4230ab3f 803 for $tmp (@XSStack) {
804 next unless defined $tmp->{functions}{$Full_func_name};
ff68c719 805 Warn("Warning: duplicate function definition '$clean_func_name' detected");
4230ab3f 806 last;
8e07c86e 807 }
4230ab3f 808 $XSStack[$XSS_work_idx]{functions}{$Full_func_name} ++ ;
809 %XsubAliases = %XsubAliasValues = ();
c2960299 810
2304df62 811 @args = split(/\s*,\s*/, $orig_args);
a0d0e21e 812 if (defined($class)) {
8fc38fda 813 my $arg0 = ((defined($static) or $func_name =~ /^new/) ? "CLASS" : "THIS");
8e07c86e 814 unshift(@args, $arg0);
815 ($orig_args = "$arg0, $orig_args") =~ s/^$arg0, $/$arg0/;
2304df62 816 }
817 $orig_args =~ s/"/\\"/g;
818 $min_args = $num_args = @args;
819 foreach $i (0..$num_args-1) {
820 if ($args[$i] =~ s/\.\.\.//) {
821 $elipsis = 1;
822 $min_args--;
c2960299 823 if ($args[$i] eq '' && $i == $num_args - 1) {
2304df62 824 pop(@args);
825 last;
826 }
827 }
8e07c86e 828 if ($args[$i] =~ /^([^=]*[^\s=])\s*=\s*(.*)/s) {
2304df62 829 $min_args--;
830 $args[$i] = $1;
831 $defaults{$args[$i]} = $2;
832 $defaults{$args[$i]} =~ s/"/\\"/g;
833 }
93d3b392 834 $proto_arg[$i+1] = "\$" ;
2304df62 835 }
a0d0e21e 836 if (defined($class)) {
2304df62 837 $func_args = join(", ", @args[1..$#args]);
838 } else {
839 $func_args = join(", ", @args);
840 }
841 @args_match{@args} = 1..@args;
842
8e07c86e 843 $PPCODE = grep(/^\s*PPCODE\s*:/, @line);
93d3b392 844 $CODE = grep(/^\s*CODE\s*:/, @line);
6c5fb52b 845 # Detect CODE: blocks which use ST(n)= or XST_m*(n,v)
846 # to set explicit return values.
847 $EXPLICIT_RETURN = ($CODE &&
848 ("@line" =~ /(\bST\s*\([^;]*=) | (\bXST_m\w+\s*\()/x ));
8e07c86e 849 $ALIAS = grep(/^\s*ALIAS\s*:/, @line);
850
2304df62 851 # print function header
a0d0e21e 852 print Q<<"EOF";
ff68c719 853#XS(XS_${Full_func_name})
2304df62 854#[[
a0d0e21e 855# dXSARGS;
93a17b20 856EOF
8e07c86e 857 print Q<<"EOF" if $ALIAS ;
858# dXSI32;
859EOF
2304df62 860 if ($elipsis) {
8e07c86e 861 $cond = ($min_args ? qq(items < $min_args) : 0);
2304df62 862 }
863 elsif ($min_args == $num_args) {
864 $cond = qq(items != $min_args);
865 }
866 else {
867 $cond = qq(items < $min_args || items > $num_args);
868 }
8990e307 869
2304df62 870 print Q<<"EOF" if $except;
871# char errbuf[1024];
872# *errbuf = '\0';
873EOF
874
8e07c86e 875 if ($ALIAS)
876 { print Q<<"EOF" if $cond }
877# if ($cond)
878# croak("Usage: %s($orig_args)", GvNAME(CvGV(cv)));
879EOF
880 else
881 { print Q<<"EOF" if $cond }
882# if ($cond)
8990e307 883# croak("Usage: $pname($orig_args)");
93a17b20 884EOF
885
a0d0e21e 886 print Q<<"EOF" if $PPCODE;
887# SP -= items;
888EOF
889
2304df62 890 # Now do a block of some sort.
93a17b20 891
2304df62 892 $condnum = 0;
8e07c86e 893 $cond = ''; # last CASE: condidional
894 push(@line, "$END:");
895 push(@line_no, $line_no[-1]);
896 $_ = '';
897 &check_cpp;
2304df62 898 while (@line) {
8e07c86e 899 &CASE_handler if check_keyword("CASE");
900 print Q<<"EOF";
901# $except [[
93a17b20 902EOF
903
904 # do initialization of input variables
905 $thisdone = 0;
906 $retvaldone = 0;
463ee0b2 907 $deferred = "";
c2960299 908 %arg_list = () ;
909 $gotRETVAL = 0;
f06db76b 910
8fc38fda 911 INPUT_handler() ;
db3b9414 912 process_keyword("INPUT|PREINIT|ALIAS|PROTOTYPE|SCOPE") ;
8fc38fda 913
db3b9414 914 print Q<<"EOF" if $ScopeThisXSUB;
915# ENTER;
916# [[
917EOF
918
a0d0e21e 919 if (!$thisdone && defined($class)) {
8fc38fda 920 if (defined($static) or $func_name =~ /^new/) {
a0d0e21e 921 print "\tchar *";
922 $var_types{"CLASS"} = "char *";
923 &generate_init("char *", 1, "CLASS");
924 }
925 else {
93a17b20 926 print "\t$class *";
927 $var_types{"THIS"} = "$class *";
928 &generate_init("$class *", 1, "THIS");
a0d0e21e 929 }
93a17b20 930 }
931
932 # do code
933 if (/^\s*NOT_IMPLEMENTED_YET/) {
4633a7c4 934 print "\n\tcroak(\"$pname: not implemented yet\");\n";
935 $_ = '' ;
93a17b20 936 } else {
937 if ($ret_type ne "void") {
938 print "\t" . &map_type($ret_type) . "\tRETVAL;\n"
939 if !$retvaldone;
940 $args_match{"RETVAL"} = 0;
941 $var_types{"RETVAL"} = $ret_type;
942 }
db3b9414 943
8e07c86e 944 print $deferred;
db3b9414 945
946 process_keyword("INIT|ALIAS|PROTOTYPE") ;
8e07c86e 947
948 if (check_keyword("PPCODE")) {
8fc38fda 949 print_section();
8e07c86e 950 death ("PPCODE must be last thing") if @line;
db3b9414 951 print "\tLEAVE;\n" if $ScopeThisXSUB;
a0d0e21e 952 print "\tPUTBACK;\n\treturn;\n";
8e07c86e 953 } elsif (check_keyword("CODE")) {
8fc38fda 954 print_section() ;
955 } elsif (defined($class) and $func_name eq "DESTROY") {
a0d0e21e 956 print "\n\t";
8e07c86e 957 print "delete THIS;\n";
93a17b20 958 } else {
959 print "\n\t";
960 if ($ret_type ne "void") {
463ee0b2 961 print "RETVAL = ";
e50aee73 962 $wantRETVAL = 1;
93a17b20 963 }
964 if (defined($static)) {
a0d0e21e 965 if ($func_name =~ /^new/) {
8fc38fda 966 $func_name = "$class";
8e07c86e 967 } else {
968 print "${class}::";
a0d0e21e 969 }
93a17b20 970 } elsif (defined($class)) {
8fc38fda 971 if ($func_name =~ /^new/) {
972 $func_name .= " $class";
973 } else {
93a17b20 974 print "THIS->";
8fc38fda 975 }
93a17b20 976 }
e50aee73 977 $func_name =~ s/^($spat)//
978 if defined($spat);
93a17b20 979 print "$func_name($func_args);\n";
93a17b20 980 }
981 }
982
983 # do output variables
8e07c86e 984 $gotRETVAL = 0;
985 undef $RETVAL_code ;
986 undef %outargs ;
8fc38fda 987 process_keyword("OUTPUT|ALIAS|PROTOTYPE");
f06db76b 988
989 # all OUTPUT done, so now push the return value on the stack
8e07c86e 990 if ($gotRETVAL && $RETVAL_code) {
991 print "\t$RETVAL_code\n";
992 } elsif ($gotRETVAL || $wantRETVAL) {
993 &generate_output($ret_type, 0, 'RETVAL');
994 }
e1f0c0aa 995 print line_directive();
f06db76b 996
93a17b20 997 # do cleanup
8fc38fda 998 process_keyword("CLEANUP|ALIAS|PROTOTYPE") ;
8e07c86e 999
db3b9414 1000 print Q<<"EOF" if $ScopeThisXSUB;
1001# ]]
1002EOF
1003 print Q<<"EOF" if $ScopeThisXSUB and not $PPCODE;
1004# LEAVE;
1005EOF
1006
93a17b20 1007 # print function trailer
8e07c86e 1008 print Q<<EOF;
2304df62 1009# ]]
8e07c86e 1010EOF
1011 print Q<<EOF if $except;
8990e307 1012# BEGHANDLERS
1013# CATCHALL
1014# sprintf(errbuf, "%s: %s\\tpropagated", Xname, Xreason);
1015# ENDHANDLERS
93a17b20 1016EOF
8e07c86e 1017 if (check_keyword("CASE")) {
1018 blurt ("Error: No `CASE:' at top of function")
1019 unless $condnum;
1020 $_ = "CASE: $_"; # Restore CASE: label
1021 next;
8990e307 1022 }
8e07c86e 1023 last if $_ eq "$END:";
1024 death(/^$BLOCK_re/o ? "Misplaced `$1:'" : "Junk at end of function");
2304df62 1025 }
a0d0e21e 1026
2304df62 1027 print Q<<EOF if $except;
1028# if (errbuf[0])
1029# croak(errbuf);
1030EOF
a0d0e21e 1031
7c5b83de 1032 if ($ret_type ne "void" or $EXPLICIT_RETURN) {
93d3b392 1033 print Q<<EOF unless $PPCODE;
a0d0e21e 1034# XSRETURN(1);
1035EOF
93d3b392 1036 } else {
1037 print Q<<EOF unless $PPCODE;
1038# XSRETURN_EMPTY;
1039EOF
1040 }
a0d0e21e 1041
2304df62 1042 print Q<<EOF;
2304df62 1043#]]
8990e307 1044#
93a17b20 1045EOF
382b8d97 1046
4230ab3f 1047 my $newXS = "newXS" ;
1048 my $proto = "" ;
1049
382b8d97 1050 # Build the prototype string for the xsub
1051 if ($ProtoThisXSUB) {
4230ab3f 1052 $newXS = "newXSproto";
1053
1054 if ($ProtoThisXSUB == 2) {
1055 # User has specified empty prototype
1056 $proto = ', ""' ;
1057 }
7d41bd0a 1058 elsif ($ProtoThisXSUB != 1) {
1059 # User has specified a prototype
4230ab3f 1060 $proto = ', "' . $ProtoThisXSUB . '"';
382b8d97 1061 }
1062 else {
1063 my $s = ';';
1064 if ($min_args < $num_args) {
1065 $s = '';
1066 $proto_arg[$min_args] .= ";" ;
1067 }
4230ab3f 1068 push @proto_arg, "$s\@"
382b8d97 1069 if $elipsis ;
1070
4230ab3f 1071 $proto = ', "' . join ("", @proto_arg) . '"';
382b8d97 1072 }
1073 }
1074
4230ab3f 1075 if (%XsubAliases) {
1076 $XsubAliases{$pname} = 0
1077 unless defined $XsubAliases{$pname} ;
1078 while ( ($name, $value) = each %XsubAliases) {
1079 push(@InitFileCode, Q<<"EOF");
1080# cv = newXS(\"$name\", XS_$Full_func_name, file);
1081# XSANY.any_i32 = $value ;
1082EOF
1083 push(@InitFileCode, Q<<"EOF") if $proto;
1084# sv_setpv((SV*)cv$proto) ;
1085EOF
1086 }
1087 }
1088 else {
1089 push(@InitFileCode,
1090 " ${newXS}(\"$pname\", XS_$Full_func_name, file$proto);\n");
1091 }
93a17b20 1092}
1093
1094# print initialization routine
8990e307 1095print Q<<"EOF";
4633a7c4 1096##ifdef __cplusplus
1097#extern "C"
1098##endif
a0d0e21e 1099#XS(boot_$Module_cname)
2304df62 1100#[[
a0d0e21e 1101# dXSARGS;
8990e307 1102# char* file = __FILE__;
1103#
93a17b20 1104EOF
1105
8fc38fda 1106print Q<<"EOF" if $WantVersionChk ;
1107# XS_VERSION_BOOTCHECK ;
1108#
1109EOF
1110
4230ab3f 1111print Q<<"EOF" if defined $XsubAliases ;
8e07c86e 1112# {
1113# CV * cv ;
1114#
1115EOF
1116
4230ab3f 1117print @InitFileCode;
a0d0e21e 1118
4230ab3f 1119print Q<<"EOF" if defined $XsubAliases ;
8e07c86e 1120# }
1121EOF
1122
a0d0e21e 1123if (@BootCode)
1124{
8e07c86e 1125 print "\n /* Initialisation Section */\n" ;
a0d0e21e 1126 print grep (s/$/\n/, @BootCode) ;
8e07c86e 1127 print "\n /* End of Initialisation Section */\n\n" ;
93a17b20 1128}
a0d0e21e 1129
e50aee73 1130print Q<<"EOF";;
1131# ST(0) = &sv_yes;
1132# XSRETURN(1);
1133#]]
1134EOF
1135
8fc38fda 1136warn("Please specify prototyping behavior for $filename (see perlxs manual)\n")
1137 unless $ProtoUsed ;
e50aee73 1138&Exit;
1139
93a17b20 1140
1141sub output_init {
2304df62 1142 local($type, $num, $init) = @_;
a0d0e21e 1143 local($arg) = "ST(" . ($num - 1) . ")";
93a17b20 1144
2304df62 1145 eval qq/print " $init\\\n"/;
93a17b20 1146}
1147
e1f0c0aa 1148sub line_directive
1149{
1150 # work out the line number
1151 my $line_no = $line_no[@line_no - @line -1] ;
1152
1153 return "#line $line_no \"$filename\"\n" ;
1154
1155}
1156
c2960299 1157sub Warn
1158{
1159 # work out the line number
1160 my $line_no = $line_no[@line_no - @line -1] ;
1161
1162 print STDERR "@_ in $filename, line $line_no\n" ;
1163}
1164
1165sub blurt
1166{
1167 Warn @_ ;
1168 $errors ++
1169}
1170
1171sub death
1172{
1173 Warn @_ ;
1174 exit 1 ;
1175}
8990e307 1176
93a17b20 1177sub generate_init {
2304df62 1178 local($type, $num, $var) = @_;
a0d0e21e 1179 local($arg) = "ST(" . ($num - 1) . ")";
2304df62 1180 local($argoff) = $num - 1;
1181 local($ntype);
1182 local($tk);
93a17b20 1183
f06db76b 1184 $type = TidyType($type) ;
c2960299 1185 blurt("Error: '$type' not in typemap"), return
1186 unless defined($type_kind{$type});
1187
2304df62 1188 ($ntype = $type) =~ s/\s*\*/Ptr/g;
8e07c86e 1189 ($subtype = $ntype) =~ s/(?:Array)?(?:Ptr)?$//;
2304df62 1190 $tk = $type_kind{$type};
1191 $tk =~ s/OBJ$/REF/ if $func_name =~ /DESTROY$/;
8e07c86e 1192 $type =~ tr/:/_/;
c2960299 1193 blurt("Error: No INPUT definition for type '$type' found"), return
1194 unless defined $input_expr{$tk} ;
2304df62 1195 $expr = $input_expr{$tk};
1196 if ($expr =~ /DO_ARRAY_ELEM/) {
c2960299 1197 blurt("Error: '$subtype' not in typemap"), return
1198 unless defined($type_kind{$subtype});
1199 blurt("Error: No INPUT definition for type '$subtype' found"), return
1200 unless defined $input_expr{$type_kind{$subtype}} ;
2304df62 1201 $subexpr = $input_expr{$type_kind{$subtype}};
1202 $subexpr =~ s/ntype/subtype/g;
1203 $subexpr =~ s/\$arg/ST(ix_$var)/g;
1204 $subexpr =~ s/\n\t/\n\t\t/g;
93d3b392 1205 $subexpr =~ s/is not of (.*\")/[arg %d] is not of $1, ix_$var + 1/g;
a0d0e21e 1206 $subexpr =~ s/\$var/${var}[ix_$var - $argoff]/;
2304df62 1207 $expr =~ s/DO_ARRAY_ELEM/$subexpr/;
1208 }
db3b9414 1209 if ($expr =~ m#/\*.*scope.*\*/#i) { # "scope" in C comments
1210 $ScopeThisXSUB = 1;
1211 }
2304df62 1212 if (defined($defaults{$var})) {
1213 $expr =~ s/(\t+)/$1 /g;
1214 $expr =~ s/ /\t/g;
1215 eval qq/print "\\t$var;\\n"/;
1216 $deferred .= eval qq/"\\n\\tif (items < $num)\\n\\t $var = $defaults{$var};\\n\\telse {\\n$expr;\\n\\t}\\n"/;
db3b9414 1217 } elsif ($ScopeThisXSUB or $expr !~ /^\t\$var =/) {
2304df62 1218 eval qq/print "\\t$var;\\n"/;
1219 $deferred .= eval qq/"\\n$expr;\\n"/;
1220 } else {
1221 eval qq/print "$expr;\\n"/;
1222 }
93a17b20 1223}
1224
1225sub generate_output {
2304df62 1226 local($type, $num, $var) = @_;
a0d0e21e 1227 local($arg) = "ST(" . ($num - ($num != 0)) . ")";
2304df62 1228 local($argoff) = $num - 1;
1229 local($ntype);
93a17b20 1230
f06db76b 1231 $type = TidyType($type) ;
2304df62 1232 if ($type =~ /^array\(([^,]*),(.*)\)/) {
1233 print "\tsv_setpvn($arg, (char *)$var, $2 * sizeof($1)), XFree((char *)$var);\n";
1234 } else {
f06db76b 1235 blurt("Error: '$type' not in typemap"), return
2304df62 1236 unless defined($type_kind{$type});
c2960299 1237 blurt("Error: No OUTPUT definition for type '$type' found"), return
1238 unless defined $output_expr{$type_kind{$type}} ;
2304df62 1239 ($ntype = $type) =~ s/\s*\*/Ptr/g;
1240 $ntype =~ s/\(\)//g;
8e07c86e 1241 ($subtype = $ntype) =~ s/(?:Array)?(?:Ptr)?$//;
2304df62 1242 $expr = $output_expr{$type_kind{$type}};
1243 if ($expr =~ /DO_ARRAY_ELEM/) {
c2960299 1244 blurt("Error: '$subtype' not in typemap"), return
1245 unless defined($type_kind{$subtype});
1246 blurt("Error: No OUTPUT definition for type '$subtype' found"), return
1247 unless defined $output_expr{$type_kind{$subtype}} ;
2304df62 1248 $subexpr = $output_expr{$type_kind{$subtype}};
1249 $subexpr =~ s/ntype/subtype/g;
1250 $subexpr =~ s/\$arg/ST(ix_$var)/g;
1251 $subexpr =~ s/\$var/${var}[ix_$var]/g;
1252 $subexpr =~ s/\n\t/\n\t\t/g;
1253 $expr =~ s/DO_ARRAY_ELEM\n/$subexpr/;
a0d0e21e 1254 eval "print qq\a$expr\a";
2304df62 1255 }
a0d0e21e 1256 elsif ($var eq 'RETVAL') {
a2baab1c 1257 if ($expr =~ /^\t\$arg = new/) {
1258 # We expect that $arg has refcnt 1, so we need to
1259 # mortalize it.
a0d0e21e 1260 eval "print qq\a$expr\a";
2304df62 1261 print "\tsv_2mortal(ST(0));\n";
93a17b20 1262 }
a2baab1c 1263 elsif ($expr =~ /^\s*\$arg\s*=/) {
1264 # We expect that $arg has refcnt >=1, so we need
1265 # to mortalize it. However, the extension may have
1266 # returned the built-in perl value, which is
1267 # read-only, thus not mortalizable. However, it is
1268 # safe to leave it as it is, since it would be
1269 # ignored by REFCNT_dec. Builtin values have REFCNT==0.
1270 eval "print qq\a$expr\a";
1271 print "\tif (SvREFCNT(ST(0))) sv_2mortal(ST(0));\n";
1272 }
2304df62 1273 else {
a2baab1c 1274 # Just hope that the entry would safely write it
1275 # over an already mortalized value. By
1276 # coincidence, something like $arg = &sv_undef
1277 # works too.
8990e307 1278 print "\tST(0) = sv_newmortal();\n";
a0d0e21e 1279 eval "print qq\a$expr\a";
463ee0b2 1280 }
2304df62 1281 }
a0d0e21e 1282 elsif ($arg =~ /^ST\(\d+\)$/) {
1283 eval "print qq\a$expr\a";
1284 }
2304df62 1285 }
93a17b20 1286}
1287
1288sub map_type {
e50aee73 1289 my($type) = @_;
93a17b20 1290
8e07c86e 1291 $type =~ tr/:/_/;
1292 $type =~ s/^array\(([^,]*),(.*)\).*/$1 */s;
1293 $type;
93a17b20 1294}
8990e307 1295
e50aee73 1296
1297sub Exit {
748a9306 1298# If this is VMS, the exit status has meaning to the shell, so we
8fc38fda 1299# use a predictable value (SS$_Normal or SS$_Abort) rather than an
1300# arbitrary number.
1301 exit ($Is_VMS ? ($errors ? 44 : 1) : $errors) ;
e50aee73 1302}