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