home *** CD-ROM | disk | FTP | other *** search
/ Acorn User 10 / AU_CD10.iso / Updates / Perl / Non-RPC / !Perl / lib / ExtUtils / xsubpp < prev   
Text File  |  1998-10-30  |  38KB  |  1,520 lines

  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. sub INTERFACE_MACRO_handler() {
  432.     my $in = merge_section();
  433.   
  434.     TrimWhitespace($in);
  435.     if ($in =~ /\s/) {        # two
  436.         ($interface_macro, $interface_macro_set) = split ' ', $in;
  437.     } else {
  438.         $interface_macro = $in;
  439.     $interface_macro_set = 'UNKNOWN_CVT'; # catch later
  440.     }
  441.     $interface = 1;        # local
  442.     $Interfaces = 1;        # global
  443. }
  444.  
  445. sub INTERFACE_handler() {
  446.     my $in = merge_section();
  447.   
  448.     TrimWhitespace($in);
  449.     
  450.     foreach (split /[\s,]+/, $in) {
  451.         $Interfaces{$_} = $_;
  452.     }
  453.     print Q<<"EOF";
  454. #    XSFUNCTION = $interface_macro($ret_type,cv,XSANY.any_dptr);
  455. EOF
  456.     $interface = 1;        # local
  457.     $Interfaces = 1;        # global
  458. }
  459.  
  460. sub CLEANUP_handler() { print_section() } 
  461. sub PREINIT_handler() { print_section() } 
  462. sub INIT_handler()    { print_section() } 
  463.  
  464. sub GetAliases
  465. {
  466.     my ($line) = @_ ;
  467.     my ($orig) = $line ;
  468.     my ($alias) ;
  469.     my ($value) ;
  470.  
  471.     # Parse alias definitions
  472.     # format is
  473.     #    alias = value alias = value ...
  474.  
  475.     while ($line =~ s/^\s*([\w:]+)\s*=\s*(\w+)\s*//) {
  476.         $alias = $1 ;
  477.         $orig_alias = $alias ;
  478.         $value = $2 ;
  479.  
  480.         # check for optional package definition in the alias
  481.     $alias = $Packprefix . $alias if $alias !~ /::/ ;
  482.         
  483.         # check for duplicate alias name & duplicate value
  484.     Warn("Warning: Ignoring duplicate alias '$orig_alias'")
  485.         if defined $XsubAliases{$alias} ;
  486.  
  487.     Warn("Warning: Aliases '$orig_alias' and '$XsubAliasValues{$value}' have identical values")
  488.         if $XsubAliasValues{$value} ;
  489.  
  490.     $XsubAliases = 1;
  491.     $XsubAliases{$alias} = $value ;
  492.     $XsubAliasValues{$value} = $orig_alias ;
  493.     }
  494.  
  495.     blurt("Error: Cannot parse ALIAS definitions from '$orig'")
  496.         if $line ;
  497. }
  498.  
  499. sub ALIAS_handler ()
  500. {
  501.     for (;  !/^$BLOCK_re/o;  $_ = shift(@line)) {
  502.     next unless /\S/;
  503.     TrimWhitespace($_) ;
  504.         GetAliases($_) if $_ ;
  505.     }
  506. }
  507.  
  508. sub REQUIRE_handler ()
  509. {
  510.     # the rest of the current line should contain a version number
  511.     my ($Ver) = $_ ;
  512.  
  513.     TrimWhitespace($Ver) ;
  514.  
  515.     death ("Error: REQUIRE expects a version number")
  516.     unless $Ver ;
  517.  
  518.     # check that the version number is of the form n.n
  519.     death ("Error: REQUIRE: expected a number, got '$Ver'")
  520.     unless $Ver =~ /^\d+(\.\d*)?/ ;
  521.  
  522.     death ("Error: xsubpp $Ver (or better) required--this is only $XSUBPP_version.")
  523.         unless $XSUBPP_version >= $Ver ; 
  524. }
  525.  
  526. sub VERSIONCHECK_handler ()
  527. {
  528.     # the rest of the current line should contain either ENABLE or
  529.     # DISABLE
  530.  
  531.     TrimWhitespace($_) ;
  532.  
  533.     # check for ENABLE/DISABLE
  534.     death ("Error: VERSIONCHECK: ENABLE/DISABLE")
  535.         unless /^(ENABLE|DISABLE)/i ;
  536.  
  537.     $WantVersionChk = 1 if $1 eq 'ENABLE' ;
  538.     $WantVersionChk = 0 if $1 eq 'DISABLE' ;
  539.  
  540. }
  541.  
  542. sub PROTOTYPE_handler ()
  543. {
  544.     my $specified ;
  545.  
  546.     death("Error: Only 1 PROTOTYPE definition allowed per xsub") 
  547.         if $proto_in_this_xsub ++ ;
  548.  
  549.     for (;  !/^$BLOCK_re/o;  $_ = shift(@line)) {
  550.     next unless /\S/;
  551.     $specified = 1 ;
  552.     TrimWhitespace($_) ;
  553.         if ($_ eq 'DISABLE') {
  554.        $ProtoThisXSUB = 0 
  555.         }
  556.         elsif ($_ eq 'ENABLE') {
  557.        $ProtoThisXSUB = 1 
  558.         }
  559.         else {
  560.             # remove any whitespace
  561.             s/\s+//g ;
  562.             death("Error: Invalid prototype '$_'")
  563.                 unless ValidProtoString($_) ;
  564.             $ProtoThisXSUB = C_string($_) ;
  565.         }
  566.     }
  567.  
  568.     # If no prototype specified, then assume empty prototype ""
  569.     $ProtoThisXSUB = 2 unless $specified ;
  570.  
  571.     $ProtoUsed = 1 ;
  572.  
  573. }
  574.  
  575. sub SCOPE_handler ()
  576. {
  577.     death("Error: Only 1 SCOPE declaration allowed per xsub") 
  578.         if $scope_in_this_xsub ++ ;
  579.  
  580.     for (;  !/^$BLOCK_re/o;  $_ = shift(@line)) {
  581.         next unless /\S/;
  582.         TrimWhitespace($_) ;
  583.         if ($_ =~ /^DISABLE/i) {
  584.            $ScopeThisXSUB = 0 
  585.         }
  586.         elsif ($_ =~ /^ENABLE/i) {
  587.            $ScopeThisXSUB = 1 
  588.         }
  589.     }
  590.  
  591. }
  592.  
  593. sub PROTOTYPES_handler ()
  594. {
  595.     # the rest of the current line should contain either ENABLE or
  596.     # DISABLE 
  597.  
  598.     TrimWhitespace($_) ;
  599.  
  600.     # check for ENABLE/DISABLE
  601.     death ("Error: PROTOTYPES: ENABLE/DISABLE")
  602.         unless /^(ENABLE|DISABLE)/i ;
  603.  
  604.     $WantPrototypes = 1 if $1 eq 'ENABLE' ;
  605.     $WantPrototypes = 0 if $1 eq 'DISABLE' ;
  606.     $ProtoUsed = 1 ;
  607.  
  608. }
  609.  
  610. sub INCLUDE_handler ()
  611. {
  612.     # the rest of the current line should contain a valid filename
  613.  
  614.     TrimWhitespace($_) ;
  615.  
  616.     death("INCLUDE: filename missing")
  617.         unless $_ ;
  618.  
  619.     death("INCLUDE: output pipe is illegal")
  620.         if /^\s*\|/ ;
  621.  
  622.     # simple minded recursion detector
  623.     death("INCLUDE loop detected")
  624.         if $IncludedFiles{$_} ;
  625.  
  626.     ++ $IncludedFiles{$_} unless /\|\s*$/ ;
  627.  
  628.     # Save the current file context.
  629.     push(@XSStack, {
  630.     type        => 'file',
  631.         LastLine        => $lastline,
  632.         LastLineNo      => $lastline_no,
  633.         Line            => \@line,
  634.         LineNo          => \@line_no,
  635.         Filename        => $filename,
  636.         Handle          => $FH,
  637.         }) ;
  638.  
  639.     ++ $FH ;
  640.  
  641.     # open the new file
  642.     open ($FH, "$_") or death("Cannot open '$_': $!") ;
  643.  
  644.     print Q<<"EOF" ;
  645. #
  646. #/* INCLUDE:  Including '$_' from '$filename' */
  647. #
  648. EOF
  649.  
  650.     $filename = $_ ;
  651.  
  652.     # Prime the pump by reading the first 
  653.     # non-blank line
  654.  
  655.     # skip leading blank lines
  656.     while (<$FH>) {
  657.         last unless /^\s*$/ ;
  658.     }
  659.  
  660.     $lastline = $_ ;
  661.     $lastline_no = $. ;
  662.  
  663. }
  664.  
  665. sub PopFile()
  666. {
  667.     return 0 unless $XSStack[-1]{type} eq 'file' ;
  668.  
  669.     my $data     = pop @XSStack ;
  670.     my $ThisFile = $filename ;
  671.     my $isPipe   = ($filename =~ /\|\s*$/) ;
  672.  
  673.     -- $IncludedFiles{$filename}
  674.         unless $isPipe ;
  675.  
  676.     close $FH ;
  677.  
  678.     $FH         = $data->{Handle} ;
  679.     $filename   = $data->{Filename} ;
  680.     $lastline   = $data->{LastLine} ;
  681.     $lastline_no = $data->{LastLineNo} ;
  682.     @line       = @{ $data->{Line} } ;
  683.     @line_no    = @{ $data->{LineNo} } ;
  684.  
  685.     if ($isPipe and $? ) {
  686.         -- $lastline_no ;
  687.         print STDERR "Error reading from pipe '$ThisFile': $! in $filename, line $lastline_no\n"  ;
  688.         exit 1 ;
  689.     }
  690.  
  691.     print Q<<"EOF" ;
  692. #
  693. #/* INCLUDE: Returning to '$filename' from '$ThisFile' */
  694. #
  695. EOF
  696.  
  697.     return 1 ;
  698. }
  699.  
  700. sub ValidProtoString ($)
  701. {
  702.     my($string) = @_ ;
  703.  
  704.     if ( $string =~ /^$proto_re+$/ ) {
  705.         return $string ;
  706.     }
  707.  
  708.     return 0 ;
  709. }
  710.  
  711. sub C_string ($)
  712. {
  713.     my($string) = @_ ;
  714.  
  715.     $string =~ s[\\][\\\\]g ;
  716.     $string ;
  717. }
  718.  
  719. sub ProtoString ($)
  720. {
  721.     my ($type) = @_ ;
  722.  
  723.     $proto_letter{$type} or "\$" ;
  724. }
  725.  
  726. sub check_cpp {
  727.     my @cpp = grep(/^\#\s*(?:if|e\w+)/, @line);
  728.     if (@cpp) {
  729.     my ($cpp, $cpplevel);
  730.     for $cpp (@cpp) {
  731.         if ($cpp =~ /^\#\s*if/) {
  732.         $cpplevel++;
  733.         } elsif (!$cpplevel) {
  734.         Warn("Warning: #else/elif/endif without #if in this function");
  735.         print STDERR "    (precede it with a blank line if the matching #if is outside the function)\n"
  736.             if $XSStack[-1]{type} eq 'if';
  737.         return;
  738.         } elsif ($cpp =~ /^\#\s*endif/) {
  739.         $cpplevel--;
  740.         }
  741.     }
  742.     Warn("Warning: #if without #endif in this function") if $cpplevel;
  743.     }
  744. }
  745.  
  746.  
  747. sub Q {
  748.     my($text) = @_;
  749.     $text =~ s/^#//gm;
  750.     $text =~ s/\[\[/{/g;
  751.     $text =~ s/\]\]/}/g;
  752.     $text;
  753. }
  754.  
  755. open($FH, $filename) or die "cannot open $filename: $!\n";
  756.  
  757. # Identify the version of xsubpp used
  758. print <<EOM ;
  759. /*
  760.  * This file was generated automatically by xsubpp version $XSUBPP_version from the 
  761.  * contents of $filename. Do not edit this file, edit $filename instead.
  762.  *
  763.  *    ANY CHANGES MADE HERE WILL BE LOST! 
  764.  *
  765.  */
  766.  
  767. EOM
  768.  
  769.  
  770. print("#line 1 \"$filename\"\n")
  771.     if $WantLineNumbers;
  772.  
  773. while (<$FH>) {
  774.     last if ($Module, $Package, $Prefix) =
  775.     /^MODULE\s*=\s*([\w:]+)(?:\s+PACKAGE\s*=\s*([\w:]+))?(?:\s+PREFIX\s*=\s*(\S+))?\s*$/;
  776.  
  777.     if ($OBJ) {
  778.         s/#if(?:def\s|\s+defined)\s*(\(__cplusplus\)|__cplusplus)/#if defined(__cplusplus) && !defined(PERL_OBJECT)/;
  779.     }
  780.     print $_;
  781. }
  782. &Exit unless defined $_;
  783.  
  784. print "$xsubpp::counter::SECTION_END_MARKER\n" if $WantLineNumbers;
  785.  
  786. $lastline    = $_;
  787. $lastline_no = $.;
  788.  
  789. # Read next xsub into @line from ($lastline, <$FH>).
  790. sub fetch_para {
  791.     # parse paragraph
  792.     death ("Error: Unterminated `#if/#ifdef/#ifndef'")
  793.     if !defined $lastline && $XSStack[-1]{type} eq 'if';
  794.     @line = ();
  795.     @line_no = () ;
  796.     return PopFile() if !defined $lastline;
  797.  
  798.     if ($lastline =~
  799.     /^MODULE\s*=\s*([\w:]+)(?:\s+PACKAGE\s*=\s*([\w:]+))?(?:\s+PREFIX\s*=\s*(\S+))?\s*$/) {
  800.     $Module = $1;
  801.     $Package = defined($2) ? $2 : '';    # keep -w happy
  802.     $Prefix  = defined($3) ? $3 : '';    # keep -w happy
  803.     $Prefix = quotemeta $Prefix ;
  804.     ($Module_cname = $Module) =~ s/\W/_/g;
  805.     ($Packid = $Package) =~ tr/:/_/;
  806.     $Packprefix = $Package;
  807.     $Packprefix .= "::" if $Packprefix ne "";
  808.     $lastline = "";
  809.     }
  810.  
  811.     for(;;) {
  812.     if ($lastline !~ /^\s*#/ ||
  813.         # CPP directives:
  814.         #    ANSI:    if ifdef ifndef elif else endif define undef
  815.         #        line error pragma
  816.         #    gcc:    warning include_next
  817.         #   obj-c:    import
  818.         #   others:    ident (gcc notes that some cpps have this one)
  819.         $lastline =~ /^#[ \t]*(?:(?:if|ifn?def|elif|else|endif|define|undef|pragma|error|warning|line\s+\d+|ident)\b|(?:include(?:_next)?|import)\s*["<].*[>"])/) {
  820.         last if $lastline =~ /^\S/ && @line && $line[-1] eq "";
  821.         push(@line, $lastline);
  822.         push(@line_no, $lastline_no) ;
  823.     }
  824.  
  825.     # Read next line and continuation lines
  826.     last unless defined($lastline = <$FH>);
  827.     $lastline_no = $.;
  828.     my $tmp_line;
  829.     $lastline .= $tmp_line
  830.         while ($lastline =~ /\\$/ && defined($tmp_line = <$FH>));
  831.         
  832.     chomp $lastline;
  833.     $lastline =~ s/^\s+$//;
  834.     }
  835.     pop(@line), pop(@line_no) while @line && $line[-1] eq "";
  836.     1;
  837. }
  838.  
  839. PARAGRAPH:
  840. while (fetch_para()) {
  841.     # Print initial preprocessor statements and blank lines
  842.     while (@line && $line[0] !~ /^[^\#]/) {
  843.     my $line = shift(@line);
  844.     print $line, "\n";
  845.     next unless $line =~ /^\#\s*((if)(?:n?def)?|elsif|else|endif)\b/;
  846.     my $statement = $+;
  847.     if ($statement eq 'if') {
  848.         $XSS_work_idx = @XSStack;
  849.         push(@XSStack, {type => 'if'});
  850.     } else {
  851.         death ("Error: `$statement' with no matching `if'")
  852.         if $XSStack[-1]{type} ne 'if';
  853.         if ($XSStack[-1]{varname}) {
  854.         push(@InitFileCode, "#endif\n");
  855.         push(@BootCode,     "#endif");
  856.         }
  857.  
  858.         my(@fns) = keys %{$XSStack[-1]{functions}};
  859.         if ($statement ne 'endif') {
  860.         # Hide the functions defined in other #if branches, and reset.
  861.         @{$XSStack[-1]{other_functions}}{@fns} = (1) x @fns;
  862.         @{$XSStack[-1]}{qw(varname functions)} = ('', {});
  863.         } else {
  864.         my($tmp) = pop(@XSStack);
  865.         0 while (--$XSS_work_idx
  866.              && $XSStack[$XSS_work_idx]{type} ne 'if');
  867.         # Keep all new defined functions
  868.         push(@fns, keys %{$tmp->{other_functions}});
  869.         @{$XSStack[$XSS_work_idx]{functions}}{@fns} = (1) x @fns;
  870.         }
  871.     }
  872.     }
  873.  
  874.     next PARAGRAPH unless @line;
  875.  
  876.     if ($XSS_work_idx && !$XSStack[$XSS_work_idx]{varname}) {
  877.     # We are inside an #if, but have not yet #defined its xsubpp variable.
  878.     print "#define $cpp_next_tmp 1\n\n";
  879.     push(@InitFileCode, "#if $cpp_next_tmp\n");
  880.     push(@BootCode,     "#if $cpp_next_tmp");
  881.     $XSStack[$XSS_work_idx]{varname} = $cpp_next_tmp++;
  882.     }
  883.  
  884.     death ("Code is not inside a function"
  885.        ." (maybe last function was ended by a blank line "
  886.        ." followed by a a statement on column one?)")
  887.     if $line[0] =~ /^\s/;
  888.  
  889.     # initialize info arrays
  890.     undef(%args_match);
  891.     undef(%var_types);
  892.     undef(%var_addr);
  893.     undef(%defaults);
  894.     undef($class);
  895.     undef($static);
  896.     undef($elipsis);
  897.     undef($wantRETVAL) ;
  898.     undef(%arg_list) ;
  899.     undef(@proto_arg) ;
  900.     undef($proto_in_this_xsub) ;
  901.     undef($scope_in_this_xsub) ;
  902.     undef($interface);
  903.     $interface_macro = 'XSINTERFACE_FUNC' ;
  904.     $interface_macro_set = 'XSINTERFACE_FUNC_SET' ;
  905.     $ProtoThisXSUB = $WantPrototypes ;
  906.     $ScopeThisXSUB = 0;
  907.  
  908.     $_ = shift(@line);
  909.     while ($kwd = check_keyword("REQUIRE|PROTOTYPES|VERSIONCHECK|INCLUDE")) {
  910.         &{"${kwd}_handler"}() ;
  911.         next PARAGRAPH unless @line ;
  912.         $_ = shift(@line);
  913.     }
  914.  
  915.     if (check_keyword("BOOT")) {
  916.     &check_cpp;
  917.     push (@BootCode, "#line $line_no[@line_no - @line] \"$filename\"")
  918.       if $WantLineNumbers && $line[0] !~ /^\s*#\s*line\b/;
  919.         push (@BootCode, @line, "") ;
  920.         next PARAGRAPH ;
  921.     }
  922.  
  923.  
  924.     # extract return type, function name and arguments
  925.     ($ret_type) = TidyType($_);
  926.  
  927.     # a function definition needs at least 2 lines
  928.     blurt ("Error: Function definition too short '$ret_type'"), next PARAGRAPH
  929.     unless @line ;
  930.  
  931.     $static = 1 if $ret_type =~ s/^static\s+//;
  932.  
  933.     $func_header = shift(@line);
  934.     blurt ("Error: Cannot parse function definition from '$func_header'"), next PARAGRAPH
  935.     unless $func_header =~ /^(?:([\w:]*)::)?(\w+)\s*\(\s*(.*?)\s*\)\s*(const)?\s*$/s;
  936.  
  937.     ($class, $func_name, $orig_args) =  ($1, $2, $3) ;
  938.     $class = "$4 $class" if $4;
  939.     ($pname = $func_name) =~ s/^($Prefix)?/$Packprefix/;
  940.     ($clean_func_name = $func_name) =~ s/^$Prefix//;
  941.     $Full_func_name = "${Packid}_$clean_func_name";
  942.     if ($Is_VMS) { $Full_func_name = $SymSet->addsym($Full_func_name); }
  943.  
  944.     # Check for duplicate function definition
  945.     for $tmp (@XSStack) {
  946.     next unless defined $tmp->{functions}{$Full_func_name};
  947.     Warn("Warning: duplicate function definition '$clean_func_name' detected");
  948.     last;
  949.     }
  950.     $XSStack[$XSS_work_idx]{functions}{$Full_func_name} ++ ;
  951.     %XsubAliases = %XsubAliasValues = %Interfaces = ();
  952.     $DoSetMagic = 1;
  953.  
  954.     @args = split(/\s*,\s*/, $orig_args);
  955.     if (defined($class)) {
  956.     my $arg0 = ((defined($static) or $func_name eq 'new')
  957.             ? "CLASS" : "THIS");
  958.     unshift(@args, $arg0);
  959.     ($orig_args = "$arg0, $orig_args") =~ s/^$arg0, $/$arg0/;
  960.     }
  961.     $orig_args =~ s/"/\\"/g;
  962.     $min_args = $num_args = @args;
  963.     foreach $i (0..$num_args-1) {
  964.         if ($args[$i] =~ s/\.\.\.//) {
  965.             $elipsis = 1;
  966.             $min_args--;
  967.             if ($args[$i] eq '' && $i == $num_args - 1) {
  968.             pop(@args);
  969.             last;
  970.             }
  971.         }
  972.         if ($args[$i] =~ /^([^=]*[^\s=])\s*=\s*(.*)/s) {
  973.             $min_args--;
  974.             $args[$i] = $1;
  975.             $defaults{$args[$i]} = $2;
  976.             $defaults{$args[$i]} =~ s/"/\\"/g;
  977.         }
  978.         $proto_arg[$i+1] = "\$" ;
  979.     }
  980.     if (defined($class)) {
  981.         $func_args = join(", ", @args[1..$#args]);
  982.     } else {
  983.         $func_args = join(", ", @args);
  984.     }
  985.     @args_match{@args} = 1..@args;
  986.  
  987.     $PPCODE = grep(/^\s*PPCODE\s*:/, @line);
  988.     $CODE = grep(/^\s*CODE\s*:/, @line);
  989.     # Detect CODE: blocks which use ST(n)= or XST_m*(n,v)
  990.     #   to set explicit return values.
  991.     $EXPLICIT_RETURN = ($CODE &&
  992.         ("@line" =~ /(\bST\s*\([^;]*=) | (\bXST_m\w+\s*\()/x ));
  993.     $ALIAS  = grep(/^\s*ALIAS\s*:/,  @line);
  994.     $INTERFACE  = grep(/^\s*INTERFACE\s*:/,  @line);
  995.  
  996.     # print function header
  997.     print Q<<"EOF";
  998. #XS(XS_${Full_func_name})
  999. #[[
  1000. #    dXSARGS;
  1001. EOF
  1002.     print Q<<"EOF" if $ALIAS ;
  1003. #    dXSI32;
  1004. EOF
  1005.     print Q<<"EOF" if $INTERFACE ;
  1006. #    dXSFUNCTION($ret_type);
  1007. EOF
  1008.     if ($elipsis) {
  1009.     $cond = ($min_args ? qq(items < $min_args) : 0);
  1010.     }
  1011.     elsif ($min_args == $num_args) {
  1012.     $cond = qq(items != $min_args);
  1013.     }
  1014.     else {
  1015.     $cond = qq(items < $min_args || items > $num_args);
  1016.     }
  1017.  
  1018.     print Q<<"EOF" if $except;
  1019. #    char errbuf[1024];
  1020. #    *errbuf = '\0';
  1021. EOF
  1022.  
  1023.     if ($ALIAS) 
  1024.       { print Q<<"EOF" if $cond }
  1025. #    if ($cond)
  1026. #       croak("Usage: %s($orig_args)", GvNAME(CvGV(cv)));
  1027. EOF
  1028.     else 
  1029.       { print Q<<"EOF" if $cond }
  1030. #    if ($cond)
  1031. #    croak("Usage: $pname($orig_args)");
  1032. EOF
  1033.  
  1034.     print Q<<"EOF" if $PPCODE;
  1035. #    SP -= items;
  1036. EOF
  1037.  
  1038.     # Now do a block of some sort.
  1039.  
  1040.     $condnum = 0;
  1041.     $cond = '';            # last CASE: condidional
  1042.     push(@line, "$END:");
  1043.     push(@line_no, $line_no[-1]);
  1044.     $_ = '';
  1045.     &check_cpp;
  1046.     while (@line) {
  1047.     &CASE_handler if check_keyword("CASE");
  1048.     print Q<<"EOF";
  1049. #   $except [[
  1050. EOF
  1051.  
  1052.     # do initialization of input variables
  1053.     $thisdone = 0;
  1054.     $retvaldone = 0;
  1055.     $deferred = "";
  1056.     %arg_list = () ;
  1057.         $gotRETVAL = 0;
  1058.  
  1059.     INPUT_handler() ;
  1060.     process_keyword("INPUT|PREINIT|INTERFACE_MACRO|C_ARGS|ALIAS|PROTOTYPE|SCOPE") ;
  1061.  
  1062.     print Q<<"EOF" if $ScopeThisXSUB;
  1063. #   ENTER;
  1064. #   [[
  1065. EOF
  1066.     
  1067.     if (!$thisdone && defined($class)) {
  1068.         if (defined($static) or $func_name eq 'new') {
  1069.         print "\tchar *";
  1070.         $var_types{"CLASS"} = "char *";
  1071.         &generate_init("char *", 1, "CLASS");
  1072.         }
  1073.         else {
  1074.         print "\t$class *";
  1075.         $var_types{"THIS"} = "$class *";
  1076.         &generate_init("$class *", 1, "THIS");
  1077.         }
  1078.     }
  1079.  
  1080.     # do code
  1081.     if (/^\s*NOT_IMPLEMENTED_YET/) {
  1082.         print "\n\tcroak(\"$pname: not implemented yet\");\n";
  1083.         $_ = '' ;
  1084.     } else {
  1085.         if ($ret_type ne "void") {
  1086.             print "\t" . &map_type($ret_type) . "\tRETVAL;\n"
  1087.                 if !$retvaldone;
  1088.             $args_match{"RETVAL"} = 0;
  1089.             $var_types{"RETVAL"} = $ret_type;
  1090.         }
  1091.  
  1092.         print $deferred;
  1093.  
  1094.         process_keyword("INIT|ALIAS|PROTOTYPE|INTERFACE_MACRO|INTERFACE|C_ARGS") ;
  1095.  
  1096.         if (check_keyword("PPCODE")) {
  1097.             print_section();
  1098.             death ("PPCODE must be last thing") if @line;
  1099.             print "\tLEAVE;\n" if $ScopeThisXSUB;
  1100.             print "\tPUTBACK;\n\treturn;\n";
  1101.         } elsif (check_keyword("CODE")) {
  1102.             print_section() ;
  1103.         } elsif (defined($class) and $func_name eq "DESTROY") {
  1104.             print "\n\t";
  1105.             print "delete THIS;\n";
  1106.         } else {
  1107.             print "\n\t";
  1108.             if ($ret_type ne "void") {
  1109.                 print "RETVAL = ";
  1110.                 $wantRETVAL = 1;
  1111.             }
  1112.             if (defined($static)) {
  1113.                 if ($func_name eq 'new') {
  1114.                 $func_name = "$class";
  1115.                 } else {
  1116.                 print "${class}::";
  1117.                 }
  1118.             } elsif (defined($class)) {
  1119.                 if ($func_name eq 'new') {
  1120.                 $func_name .= " $class";
  1121.                 } else {
  1122.                 print "THIS->";
  1123.                 }
  1124.             }
  1125.             $func_name =~ s/^($spat)//
  1126.                 if defined($spat);
  1127.             $func_name = 'XSFUNCTION' if $interface;
  1128.             print "$func_name($func_args);\n";
  1129.         }
  1130.     }
  1131.  
  1132.     # do output variables
  1133.     $gotRETVAL = 0;
  1134.     undef $RETVAL_code ;
  1135.     undef %outargs ;
  1136.         process_keyword("OUTPUT|ALIAS|PROTOTYPE"); 
  1137.  
  1138.     # all OUTPUT done, so now push the return value on the stack
  1139.     if ($gotRETVAL && $RETVAL_code) {
  1140.         print "\t$RETVAL_code\n";
  1141.     } elsif ($gotRETVAL || $wantRETVAL) {
  1142.         # RETVAL almost never needs SvSETMAGIC()
  1143.         &generate_output($ret_type, 0, 'RETVAL', 0);
  1144.     }
  1145.  
  1146.     # do cleanup
  1147.     process_keyword("CLEANUP|ALIAS|PROTOTYPE") ;
  1148.  
  1149.     print Q<<"EOF" if $ScopeThisXSUB;
  1150. #   ]]
  1151. EOF
  1152.     print Q<<"EOF" if $ScopeThisXSUB and not $PPCODE;
  1153. #   LEAVE;
  1154. EOF
  1155.  
  1156.     # print function trailer
  1157.     print Q<<EOF;
  1158. #    ]]
  1159. EOF
  1160.     print Q<<EOF if $except;
  1161. #    BEGHANDLERS
  1162. #    CATCHALL
  1163. #    sprintf(errbuf, "%s: %s\\tpropagated", Xname, Xreason);
  1164. #    ENDHANDLERS
  1165. EOF
  1166.     if (check_keyword("CASE")) {
  1167.         blurt ("Error: No `CASE:' at top of function")
  1168.         unless $condnum;
  1169.         $_ = "CASE: $_";    # Restore CASE: label
  1170.         next;
  1171.     }
  1172.     last if $_ eq "$END:";
  1173.     death(/^$BLOCK_re/o ? "Misplaced `$1:'" : "Junk at end of function");
  1174.     }
  1175.  
  1176.     print Q<<EOF if $except;
  1177. #    if (errbuf[0])
  1178. #    croak(errbuf);
  1179. EOF
  1180.  
  1181.     if ($ret_type ne "void" or $EXPLICIT_RETURN) {
  1182.         print Q<<EOF unless $PPCODE;
  1183. #    XSRETURN(1);
  1184. EOF
  1185.     } else {
  1186.         print Q<<EOF unless $PPCODE;
  1187. #    XSRETURN_EMPTY;
  1188. EOF
  1189.     }
  1190.  
  1191.     print Q<<EOF;
  1192. #]]
  1193. #
  1194. EOF
  1195.  
  1196.     my $newXS = "newXS" ;
  1197.     my $proto = "" ;
  1198.  
  1199.     # Build the prototype string for the xsub
  1200.     if ($ProtoThisXSUB) {
  1201.     $newXS = "newXSproto";
  1202.  
  1203.     if ($ProtoThisXSUB eq 2) {
  1204.         # User has specified empty prototype
  1205.         $proto = ', ""' ;
  1206.     }
  1207.         elsif ($ProtoThisXSUB ne 1) {
  1208.             # User has specified a prototype
  1209.             $proto = ', "' . $ProtoThisXSUB . '"';
  1210.         }
  1211.         else {
  1212.         my $s = ';';
  1213.             if ($min_args < $num_args)  {
  1214.                 $s = ''; 
  1215.         $proto_arg[$min_args] .= ";" ;
  1216.         }
  1217.             push @proto_arg, "$s\@" 
  1218.                 if $elipsis ;
  1219.     
  1220.             $proto = ', "' . join ("", @proto_arg) . '"';
  1221.         }
  1222.     }
  1223.  
  1224.     if (%XsubAliases) {
  1225.     $XsubAliases{$pname} = 0 
  1226.         unless defined $XsubAliases{$pname} ;
  1227.     while ( ($name, $value) = each %XsubAliases) {
  1228.         push(@InitFileCode, Q<<"EOF");
  1229. #        cv = newXS(\"$name\", XS_$Full_func_name, file);
  1230. #        XSANY.any_i32 = $value ;
  1231. EOF
  1232.     push(@InitFileCode, Q<<"EOF") if $proto;
  1233. #        sv_setpv((SV*)cv$proto) ;
  1234. EOF
  1235.         }
  1236.     } 
  1237.     elsif ($interface) {
  1238.     while ( ($name, $value) = each %Interfaces) {
  1239.         $name = "$Package\::$name" unless $name =~ /::/;
  1240.         push(@InitFileCode, Q<<"EOF");
  1241. #        cv = newXS(\"$name\", XS_$Full_func_name, file);
  1242. #        $interface_macro_set(cv,$value) ;
  1243. EOF
  1244.         push(@InitFileCode, Q<<"EOF") if $proto;
  1245. #        sv_setpv((SV*)cv$proto) ;
  1246. EOF
  1247.         }
  1248.     }
  1249.     else {
  1250.     push(@InitFileCode,
  1251.          "        ${newXS}(\"$pname\", XS_$Full_func_name, file$proto);\n");
  1252.     }
  1253. }
  1254.  
  1255. # print initialization routine
  1256.  
  1257. print Q<<"EOF";
  1258. ##ifdef __cplusplus
  1259. #extern "C"
  1260. ##endif
  1261. EOF
  1262.  
  1263. if ($WantCAPI) {
  1264. print Q<<"EOF";
  1265. ##ifdef PERL_CAPI
  1266. #XS(boot__CAPI_entry)
  1267. ##else
  1268. EOF
  1269. }
  1270.  
  1271. print Q<<"EOF";
  1272. #XS(boot_$Module_cname)
  1273. EOF
  1274.  
  1275. if ($WantCAPI) {
  1276. print Q<<"EOF";
  1277. ##endif    /* PERL_CAPI */
  1278. EOF
  1279. }
  1280.  
  1281. print Q<<"EOF";
  1282. #[[
  1283. #    dXSARGS;
  1284. #    char* file = __FILE__;
  1285. #
  1286. EOF
  1287.  
  1288. print Q<<"EOF" if $WantVersionChk ;
  1289. #    XS_VERSION_BOOTCHECK ;
  1290. #
  1291. EOF
  1292.  
  1293. print Q<<"EOF" if defined $XsubAliases or defined $Interfaces ;
  1294. #    {
  1295. #        CV * cv ;
  1296. #
  1297. EOF
  1298.  
  1299. print @InitFileCode;
  1300.  
  1301. print Q<<"EOF" if defined $XsubAliases or defined $Interfaces ;
  1302. #    }
  1303. EOF
  1304.  
  1305. if (@BootCode)
  1306. {
  1307.     print "\n    /* Initialisation Section */\n\n" ;
  1308.     @line = @BootCode;
  1309.     print_section();
  1310.     print "\n    /* End of Initialisation Section */\n\n" ;
  1311. }
  1312.  
  1313. print Q<<"EOF";;
  1314. #    XSRETURN_YES;
  1315. #]]
  1316. #
  1317. EOF
  1318.  
  1319. if ($WantCAPI) { 
  1320. print Q<<"EOF";
  1321. ##ifdef PERL_CAPI
  1322. ##define XSCAPI(name) void name(CV* cv, void* pPerl)
  1323. #
  1324. ##ifdef __cplusplus
  1325. #extern "C"
  1326. ##endif
  1327. #XSCAPI(boot_$Module_cname)
  1328. #[[
  1329. #    SetCPerlObj(pPerl);
  1330. #    boot__CAPI_entry(cv);
  1331. #]]
  1332. ##endif    /* PERL_CAPI */
  1333. EOF
  1334. }
  1335.  
  1336. warn("Please specify prototyping behavior for $filename (see perlxs manual)\n") 
  1337.     unless $ProtoUsed ;
  1338. &Exit;
  1339.  
  1340. sub output_init {
  1341.     local($type, $num, $var, $init) = @_;
  1342.     local($arg) = "ST(" . ($num - 1) . ")";
  1343.  
  1344.     if(  $init =~ /^=/  ) {
  1345.     eval qq/print "\\t$var $init\\n"/;
  1346.     warn $@   if  $@;
  1347.     } else {
  1348.     if(  $init =~ s/^\+//  &&  $num  ) {
  1349.         &generate_init($type, $num, $var);
  1350.     } else {
  1351.         eval qq/print "\\t$var;\\n"/;
  1352.         warn $@   if  $@;
  1353.         $init =~ s/^;//;
  1354.     }
  1355.     $deferred .= eval qq/"\\n\\t$init\\n"/;
  1356.     warn $@   if  $@;
  1357.     }
  1358. }
  1359.  
  1360. sub Warn
  1361. {
  1362.     # work out the line number
  1363.     my $line_no = $line_no[@line_no - @line -1] ;
  1364.  
  1365.     print STDERR "@_ in $filename, line $line_no\n" ;
  1366. }
  1367.  
  1368. sub blurt 
  1369.     Warn @_ ;
  1370.     $errors ++ 
  1371. }
  1372.  
  1373. sub death
  1374. {
  1375.     Warn @_ ;
  1376.     exit 1 ;
  1377. }
  1378.  
  1379. sub generate_init {
  1380.     local($type, $num, $var) = @_;
  1381.     local($arg) = "ST(" . ($num - 1) . ")";
  1382.     local($argoff) = $num - 1;
  1383.     local($ntype);
  1384.     local($tk);
  1385.  
  1386.     $type = TidyType($type) ;
  1387.     blurt("Error: '$type' not in typemap"), return 
  1388.     unless defined($type_kind{$type});
  1389.  
  1390.     ($ntype = $type) =~ s/\s*\*/Ptr/g;
  1391.     ($subtype = $ntype) =~ s/(?:Array)?(?:Ptr)?$//;
  1392.     $tk = $type_kind{$type};
  1393.     $tk =~ s/OBJ$/REF/ if $func_name =~ /DESTROY$/;
  1394.     $type =~ tr/:/_/;
  1395.     blurt("Error: No INPUT definition for type '$type' found"), return
  1396.         unless defined $input_expr{$tk} ;
  1397.     $expr = $input_expr{$tk};
  1398.     if ($expr =~ /DO_ARRAY_ELEM/) {
  1399.         blurt("Error: '$subtype' not in typemap"), return 
  1400.         unless defined($type_kind{$subtype});
  1401.         blurt("Error: No INPUT definition for type '$subtype' found"), return
  1402.             unless defined $input_expr{$type_kind{$subtype}} ;
  1403.     $subexpr = $input_expr{$type_kind{$subtype}};
  1404.     $subexpr =~ s/ntype/subtype/g;
  1405.     $subexpr =~ s/\$arg/ST(ix_$var)/g;
  1406.     $subexpr =~ s/\n\t/\n\t\t/g;
  1407.     $subexpr =~ s/is not of (.*\")/[arg %d] is not of $1, ix_$var + 1/g;
  1408.     $subexpr =~ s/\$var/${var}[ix_$var - $argoff]/;
  1409.     $expr =~ s/DO_ARRAY_ELEM/$subexpr/;
  1410.     }
  1411.     if ($expr =~ m#/\*.*scope.*\*/#i) { # "scope" in C comments
  1412.         $ScopeThisXSUB = 1;
  1413.     }
  1414.     if (defined($defaults{$var})) {
  1415.         $expr =~ s/(\t+)/$1    /g;
  1416.         $expr =~ s/        /\t/g;
  1417.         eval qq/print "\\t$var;\\n"/;
  1418.         warn $@   if  $@;
  1419.         $deferred .= eval qq/"\\n\\tif (items < $num)\\n\\t    $var = $defaults{$var};\\n\\telse {\\n$expr;\\n\\t}\\n"/;
  1420.         warn $@   if  $@;
  1421.     } elsif ($ScopeThisXSUB or $expr !~ /^\t\$var =/) {
  1422.         eval qq/print "\\t$var;\\n"/;
  1423.         warn $@   if  $@;
  1424.         $deferred .= eval qq/"\\n$expr;\\n"/;
  1425.         warn $@   if  $@;
  1426.     } else {
  1427.         eval qq/print "$expr;\\n"/;
  1428.         warn $@   if  $@;
  1429.     }
  1430. }
  1431.  
  1432. sub generate_output {
  1433.     local($type, $num, $var, $do_setmagic) = @_;
  1434.     local($arg) = "ST(" . ($num - ($num != 0)) . ")";
  1435.     local($argoff) = $num - 1;
  1436.     local($ntype);
  1437.  
  1438.     $type = TidyType($type) ;
  1439.     if ($type =~ /^array\(([^,]*),(.*)\)/) {
  1440.         print "\tsv_setpvn($arg, (char *)$var, $2 * sizeof($1)), XFree((char *)$var);\n";
  1441.         print "\tSvSETMAGIC($arg);\n" if $do_setmagic;
  1442.     } else {
  1443.         blurt("Error: '$type' not in typemap"), return
  1444.         unless defined($type_kind{$type});
  1445.             blurt("Error: No OUTPUT definition for type '$type' found"), return
  1446.                 unless defined $output_expr{$type_kind{$type}} ;
  1447.         ($ntype = $type) =~ s/\s*\*/Ptr/g;
  1448.         $ntype =~ s/\(\)//g;
  1449.         ($subtype = $ntype) =~ s/(?:Array)?(?:Ptr)?$//;
  1450.         $expr = $output_expr{$type_kind{$type}};
  1451.         if ($expr =~ /DO_ARRAY_ELEM/) {
  1452.             blurt("Error: '$subtype' not in typemap"), return
  1453.             unless defined($type_kind{$subtype});
  1454.                 blurt("Error: No OUTPUT definition for type '$subtype' found"), return
  1455.                     unless defined $output_expr{$type_kind{$subtype}} ;
  1456.         $subexpr = $output_expr{$type_kind{$subtype}};
  1457.         $subexpr =~ s/ntype/subtype/g;
  1458.         $subexpr =~ s/\$arg/ST(ix_$var)/g;
  1459.         $subexpr =~ s/\$var/${var}[ix_$var]/g;
  1460.         $subexpr =~ s/\n\t/\n\t\t/g;
  1461.         $expr =~ s/DO_ARRAY_ELEM\n/$subexpr/;
  1462.         eval "print qq\a$expr\a";
  1463.         warn $@   if  $@;
  1464.         print "\t\tSvSETMAGIC(ST(ix_$var));\n" if $do_setmagic;
  1465.         }
  1466.         elsif ($var eq 'RETVAL') {
  1467.         if ($expr =~ /^\t\$arg = new/) {
  1468.             # We expect that $arg has refcnt 1, so we need to
  1469.             # mortalize it.
  1470.             eval "print qq\a$expr\a";
  1471.             warn $@   if  $@;
  1472.             print "\tsv_2mortal(ST(0));\n";
  1473.             print "\tSvSETMAGIC(ST(0));\n" if $do_setmagic;
  1474.         }
  1475.         elsif ($expr =~ /^\s*\$arg\s*=/) {
  1476.             # We expect that $arg has refcnt >=1, so we need
  1477.             # to mortalize it!
  1478.             eval "print qq\a$expr\a";
  1479.             warn $@   if  $@;
  1480.             print "\tsv_2mortal(ST(0));\n";
  1481.             print "\tSvSETMAGIC(ST(0));\n" if $do_setmagic;
  1482.         }
  1483.         else {
  1484.             # Just hope that the entry would safely write it
  1485.             # over an already mortalized value. By
  1486.             # coincidence, something like $arg = &sv_undef
  1487.             # works too.
  1488.             print "\tST(0) = sv_newmortal();\n";
  1489.             eval "print qq\a$expr\a";
  1490.             warn $@   if  $@;
  1491.             # new mortals don't have set magic
  1492.         }
  1493.         }
  1494.         elsif ($arg =~ /^ST\(\d+\)$/) {
  1495.         eval "print qq\a$expr\a";
  1496.         warn $@   if  $@;
  1497.         print "\tSvSETMAGIC($arg);\n" if $do_setmagic;
  1498.         }
  1499.     }
  1500. }
  1501.  
  1502. sub map_type {
  1503.     my($type) = @_;
  1504.  
  1505.     $type =~ tr/:/_/;
  1506.     $type =~ s/^array\(([^,]*),(.*)\).*/$1 */s;
  1507.     $type;
  1508. }
  1509.  
  1510.  
  1511. sub Exit {
  1512. # If this is VMS, the exit status has meaning to the shell, so we
  1513. # use a predictable value (SS$_Normal or SS$_Abort) rather than an
  1514. # arbitrary number.
  1515. #    exit ($Is_VMS ? ($errors ? 44 : 1) : $errors) ;
  1516.     exit ($errors ? 1 : 0);
  1517. }
  1518.