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