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