[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/se3-unattended/var/se3/unattended/install/linuxaux/opt/perl/lib/5.10.0/ExtUtils/ -> ParseXS.pm (source)

   1  package ExtUtils::ParseXS;
   2  
   3  use 5.006;  # We use /??{}/ in regexes
   4  use Cwd;
   5  use Config;
   6  use File::Basename;
   7  use File::Spec;
   8  use Symbol;
   9  
  10  require Exporter;
  11  
  12  @ISA = qw(Exporter);
  13  @EXPORT_OK = qw(process_file);
  14  
  15  # use strict;  # One of these days...
  16  
  17  my(@XSStack);    # Stack of conditionals and INCLUDEs
  18  my($XSS_work_idx, $cpp_next_tmp);
  19  
  20  use vars qw($VERSION);
  21  $VERSION = '2.18_02';
  22  
  23  use vars qw(%input_expr %output_expr $ProtoUsed @InitFileCode $FH $proto_re $Overload $errors $Fallback
  24          $cplusplus $hiertype $WantPrototypes $WantVersionChk $except $WantLineNumbers
  25          $WantOptimize $process_inout $process_argtypes @tm
  26          $dir $filename $filepathname %IncludedFiles
  27          %type_kind %proto_letter
  28              %targetable $BLOCK_re $lastline $lastline_no
  29              $Package $Prefix @line @BootCode %args_match %defaults %var_types %arg_list @proto_arg
  30              $processing_arg_with_types %argtype_seen @outlist %in_out %lengthof
  31              $proto_in_this_xsub $scope_in_this_xsub $interface $prepush_done $interface_macro $interface_macro_set
  32              $ProtoThisXSUB $ScopeThisXSUB $xsreturn
  33              @line_no $ret_type $func_header $orig_args
  34         ); # Add these just to get compilation to happen.
  35  
  36  
  37  sub process_file {
  38    
  39    # Allow for $package->process_file(%hash) in the future
  40    my ($pkg, %args) = @_ % 2 ? @_ : (__PACKAGE__, @_);
  41    
  42    $ProtoUsed = exists $args{prototypes};
  43    
  44    # Set defaults.
  45    %args = (
  46         # 'C++' => 0, # Doesn't seem to *do* anything...
  47         hiertype => 0,
  48         except => 0,
  49         prototypes => 0,
  50         versioncheck => 1,
  51         linenumbers => 1,
  52         optimize => 1,
  53         prototypes => 0,
  54         inout => 1,
  55         argtypes => 1,
  56         typemap => [],
  57         output => \*STDOUT,
  58         csuffix => '.c',
  59         %args,
  60        );
  61  
  62    # Global Constants
  63    
  64    my ($Is_VMS, $SymSet);
  65    if ($^O eq 'VMS') {
  66      $Is_VMS = 1;
  67      # Establish set of global symbols with max length 28, since xsubpp
  68      # will later add the 'XS_' prefix.
  69      require ExtUtils::XSSymSet;
  70      $SymSet = new ExtUtils::XSSymSet 28;
  71    }
  72    @XSStack = ({type => 'none'});
  73    ($XSS_work_idx, $cpp_next_tmp) = (0, "XSubPPtmpAAAA");
  74    @InitFileCode = ();
  75    $FH = Symbol::gensym();
  76    $proto_re = "[" . quotemeta('\$%&*@;[]') . "]" ;
  77    $Overload = 0;
  78    $errors = 0;
  79    $Fallback = 'PL_sv_undef';
  80  
  81    # Most of the 1500 lines below uses these globals.  We'll have to
  82    # clean this up sometime, probably.  For now, we just pull them out
  83    # of %args.  -Ken
  84    
  85    $cplusplus = $args{'C++'};
  86    $hiertype = $args{hiertype};
  87    $WantPrototypes = $args{prototypes};
  88    $WantVersionChk = $args{versioncheck};
  89    $except = $args{except} ? ' TRY' : '';
  90    $WantLineNumbers = $args{linenumbers};
  91    $WantOptimize = $args{optimize};
  92    $process_inout = $args{inout};
  93    $process_argtypes = $args{argtypes};
  94    @tm = ref $args{typemap} ? @{$args{typemap}} : ($args{typemap});
  95    
  96    for ($args{filename}) {
  97      die "Missing required parameter 'filename'" unless $_;
  98      $filepathname = $_;
  99      ($dir, $filename) = (dirname($_), basename($_));
 100      $filepathname =~ s/\\/\\\\/g;
 101      $IncludedFiles{$_}++;
 102    }
 103    
 104    # Open the input file
 105    open($FH, $args{filename}) or die "cannot open $args{filename}: $!\n";
 106  
 107    # Open the output file if given as a string.  If they provide some
 108    # other kind of reference, trust them that we can print to it.
 109    if (not ref $args{output}) {
 110      open my($fh), "> $args{output}" or die "Can't create $args{output}: $!";
 111      $args{outfile} = $args{output};
 112      $args{output} = $fh;
 113    }
 114  
 115    # Really, we shouldn't have to chdir() or select() in the first
 116    # place.  For now, just save & restore.
 117    my $orig_cwd = cwd();
 118    my $orig_fh = select();
 119    
 120    chdir($dir);
 121    my $pwd = cwd();
 122    my $csuffix = $args{csuffix};
 123    
 124    if ($WantLineNumbers) {
 125      my $cfile;
 126      if ( $args{outfile} ) {
 127        $cfile = $args{outfile};
 128      } else {
 129        $cfile = $args{filename};
 130        $cfile =~ s/\.xs$/$csuffix/i or $cfile .= $csuffix;
 131      }
 132      tie(*PSEUDO_STDOUT, 'ExtUtils::ParseXS::CountLines', $cfile, $args{output});
 133      select PSEUDO_STDOUT;
 134    } else {
 135      select $args{output};
 136    }
 137  
 138    foreach my $typemap (@tm) {
 139      die "Can't find $typemap in $pwd\n" unless -r $typemap;
 140    }
 141  
 142    push @tm, standard_typemap_locations();
 143  
 144    foreach my $typemap (@tm) {
 145      next unless -f $typemap ;
 146      # skip directories, binary files etc.
 147      warn("Warning: ignoring non-text typemap file '$typemap'\n"), next
 148        unless -T $typemap ;
 149      open(TYPEMAP, $typemap)
 150        or warn ("Warning: could not open typemap file '$typemap': $!\n"), next;
 151      my $mode = 'Typemap';
 152      my $junk = "" ;
 153      my $current = \$junk;
 154      while (<TYPEMAP>) {
 155        next if /^\s*        #/;
 156          my $line_no = $. + 1;
 157        if (/^INPUT\s*$/) {
 158      $mode = 'Input';   $current = \$junk;  next;
 159        }
 160        if (/^OUTPUT\s*$/) {
 161      $mode = 'Output';  $current = \$junk;  next;
 162        }
 163        if (/^TYPEMAP\s*$/) {
 164      $mode = 'Typemap'; $current = \$junk;  next;
 165        }
 166        if ($mode eq 'Typemap') {
 167      chomp;
 168      my $line = $_ ;
 169      TrimWhitespace($_) ;
 170      # skip blank lines and comment lines
 171      next if /^$/ or /^#/ ;
 172      my($type,$kind, $proto) = /^\s*(.*?\S)\s+(\S+)\s*($proto_re*)\s*$/ or
 173        warn("Warning: File '$typemap' Line $. '$line' TYPEMAP entry needs 2 or 3 columns\n"), next;
 174      $type = TidyType($type) ;
 175      $type_kind{$type} = $kind ;
 176      # prototype defaults to '$'
 177      $proto = "\$" unless $proto ;
 178      warn("Warning: File '$typemap' Line $. '$line' Invalid prototype '$proto'\n")
 179        unless ValidProtoString($proto) ;
 180      $proto_letter{$type} = C_string($proto) ;
 181        } elsif (/^\s/) {
 182      $$current .= $_;
 183        } elsif ($mode eq 'Input') {
 184      s/\s+$//;
 185      $input_expr{$_} = '';
 186      $current = \$input_expr{$_};
 187        } else {
 188      s/\s+$//;
 189      $output_expr{$_} = '';
 190      $current = \$output_expr{$_};
 191        }
 192      }
 193      close(TYPEMAP);
 194    }
 195  
 196    foreach my $value (values %input_expr) {
 197      $value =~ s/;*\s+\z//;
 198      # Move C pre-processor instructions to column 1 to be strictly ANSI
 199      # conformant. Some pre-processors are fussy about this.
 200      $value =~ s/^\s+#/#/mg;
 201    }
 202    foreach my $value (values %output_expr) {
 203      # And again.
 204      $value =~ s/^\s+#/#/mg;
 205    }
 206  
 207    my ($cast, $size);
 208    our $bal = qr[(?:(?>[^()]+)|\((??{ $bal })\))*]; # ()-balanced
 209    $cast = qr[(?:\(\s*SV\s*\*\s*\)\s*)?]; # Optional (SV*) cast
 210    $size = qr[,\s* (??{ $bal }) ]x; # Third arg (to setpvn)
 211  
 212    foreach my $key (keys %output_expr) {
 213      BEGIN { $^H |= 0x00200000 }; # Equivalent to: use re 'eval', but hardcoded so we can compile re.xs
 214  
 215      my ($t, $with_size, $arg, $sarg) =
 216        ($output_expr{$key} =~
 217         m[^ \s+ sv_set ( [iunp] ) v (n)?    # Type, is_setpvn
 218       \s* \( \s* $cast \$arg \s* ,
 219       \s* ( (??{ $bal }) )    # Set from
 220       ( (??{ $size }) )?    # Possible sizeof set-from
 221       \) \s* ; \s* $
 222      ]x);
 223      $targetable{$key} = [$t, $with_size, $arg, $sarg] if $t;
 224    }
 225  
 226    my $END = "!End!\n\n";        # "impossible" keyword (multiple newline)
 227  
 228    # Match an XS keyword
 229    $BLOCK_re= '\s*(' . join('|', qw(
 230                     REQUIRE BOOT CASE PREINIT INPUT INIT CODE PPCODE OUTPUT
 231                     CLEANUP ALIAS ATTRS PROTOTYPES PROTOTYPE VERSIONCHECK INCLUDE
 232                     SCOPE INTERFACE INTERFACE_MACRO C_ARGS POSTCALL OVERLOAD FALLBACK
 233                    )) . "|$END)\\s*:";
 234  
 235    
 236    our ($C_group_rex, $C_arg);
 237    # Group in C (no support for comments or literals)
 238    $C_group_rex = qr/ [({\[]
 239                 (?: (?> [^()\[\]{}]+ ) | (??{ $C_group_rex }) )*
 240                 [)}\]] /x ;
 241    # Chunk in C without comma at toplevel (no comments):
 242    $C_arg = qr/ (?: (?> [^()\[\]{},"']+ )
 243           |   (??{ $C_group_rex })
 244           |   " (?: (?> [^\\"]+ )
 245             |   \\.
 246             )* "        # String literal
 247                  |   ' (?: (?> [^\\']+ ) | \\. )* ' # Char literal
 248           )* /xs;
 249    
 250    # Identify the version of xsubpp used
 251    print <<EOM ;
 252  /*
 253   * This file was generated automatically by ExtUtils::ParseXS version $VERSION from the
 254   * contents of $filename. Do not edit this file, edit $filename instead.
 255   *
 256   *    ANY CHANGES MADE HERE WILL BE LOST! 
 257   *
 258   */
 259  
 260  EOM
 261  
 262  
 263    print("#line 1 \"$filepathname\"\n")
 264      if $WantLineNumbers;
 265  
 266    firstmodule:
 267    while (<$FH>) {
 268      if (/^=/) {
 269        my $podstartline = $.;
 270        do {
 271      if (/^=cut\s*$/) {
 272        # We can't just write out a /* */ comment, as our embedded
 273        # POD might itself be in a comment. We can't put a /**/
 274        # comment inside #if 0, as the C standard says that the source
 275        # file is decomposed into preprocessing characters in the stage
 276        # before preprocessing commands are executed.
 277        # I don't want to leave the text as barewords, because the spec
 278        # isn't clear whether macros are expanded before or after
 279        # preprocessing commands are executed, and someone pathological
 280        # may just have defined one of the 3 words as a macro that does
 281        # something strange. Multiline strings are illegal in C, so
 282        # the "" we write must be a string literal. And they aren't
 283        # concatenated until 2 steps later, so we are safe.
 284        #     - Nicholas Clark
 285        print("#if 0\n  \"Skipped embedded POD.\"\n#endif\n");
 286        printf("#line %d \"$filepathname\"\n", $. + 1)
 287          if $WantLineNumbers;
 288        next firstmodule
 289      }
 290      
 291        } while (<$FH>);
 292        # At this point $. is at end of file so die won't state the start
 293        # of the problem, and as we haven't yet read any lines &death won't
 294        # show the correct line in the message either.
 295        die ("Error: Unterminated pod in $filename, line $podstartline\n")
 296      unless $lastline;
 297      }
 298      last if ($Package, $Prefix) =
 299        /^MODULE\s*=\s*[\w:]+(?:\s+PACKAGE\s*=\s*([\w:]+))?(?:\s+PREFIX\s*=\s*(\S+))?\s*$/;
 300      
 301      print $_;
 302    }
 303    unless (defined $_) {
 304      warn "Didn't find a 'MODULE ... PACKAGE ... PREFIX' line\n";
 305      exit 0; # Not a fatal error for the caller process
 306    }
 307  
 308      print <<"EOF";
 309  #ifndef PERL_UNUSED_VAR
 310  #  define PERL_UNUSED_VAR(var) if (0) var = var
 311  #endif
 312  
 313  EOF
 314  
 315    print 'ExtUtils::ParseXS::CountLines'->end_marker, "\n" if $WantLineNumbers;
 316  
 317    $lastline    = $_;
 318    $lastline_no = $.;
 319  
 320   PARAGRAPH:
 321    while (fetch_para()) {
 322      # Print initial preprocessor statements and blank lines
 323      while (@line && $line[0] !~ /^[^\#]/) {
 324        my $line = shift(@line);
 325        print $line, "\n";
 326        next unless $line =~ /^\#\s*((if)(?:n?def)?|elsif|else|endif)\b/;
 327        my $statement = $+;
 328        if ($statement eq 'if') {
 329      $XSS_work_idx = @XSStack;
 330      push(@XSStack, {type => 'if'});
 331        } else {
 332      death ("Error: `$statement' with no matching `if'")
 333        if $XSStack[-1]{type} ne 'if';
 334      if ($XSStack[-1]{varname}) {
 335        push(@InitFileCode, "#endif\n");
 336        push(@BootCode,     "#endif");
 337      }
 338      
 339      my(@fns) = keys %{$XSStack[-1]{functions}};
 340      if ($statement ne 'endif') {
 341        # Hide the functions defined in other #if branches, and reset.
 342        @{$XSStack[-1]{other_functions}}{@fns} = (1) x @fns;
 343        @{$XSStack[-1]}{qw(varname functions)} = ('', {});
 344      } else {
 345        my($tmp) = pop(@XSStack);
 346        0 while (--$XSS_work_idx
 347             && $XSStack[$XSS_work_idx]{type} ne 'if');
 348        # Keep all new defined functions
 349        push(@fns, keys %{$tmp->{other_functions}});
 350        @{$XSStack[$XSS_work_idx]{functions}}{@fns} = (1) x @fns;
 351      }
 352        }
 353      }
 354      
 355      next PARAGRAPH unless @line;
 356      
 357      if ($XSS_work_idx && !$XSStack[$XSS_work_idx]{varname}) {
 358        # We are inside an #if, but have not yet #defined its xsubpp variable.
 359        print "#define $cpp_next_tmp 1\n\n";
 360        push(@InitFileCode, "#if $cpp_next_tmp\n");
 361        push(@BootCode,     "#if $cpp_next_tmp");
 362        $XSStack[$XSS_work_idx]{varname} = $cpp_next_tmp++;
 363      }
 364  
 365      death ("Code is not inside a function"
 366         ." (maybe last function was ended by a blank line "
 367         ." followed by a statement on column one?)")
 368        if $line[0] =~ /^\s/;
 369      
 370      my ($class, $externC, $static, $ellipsis, $wantRETVAL, $RETVAL_no_return);
 371      my (@fake_INPUT_pre);    # For length(s) generated variables
 372      my (@fake_INPUT);
 373      
 374      # initialize info arrays
 375      undef(%args_match);
 376      undef(%var_types);
 377      undef(%defaults);
 378      undef(%arg_list) ;
 379      undef(@proto_arg) ;
 380      undef($processing_arg_with_types) ;
 381      undef(%argtype_seen) ;
 382      undef(@outlist) ;
 383      undef(%in_out) ;
 384      undef(%lengthof) ;
 385      undef($proto_in_this_xsub) ;
 386      undef($scope_in_this_xsub) ;
 387      undef($interface);
 388      undef($prepush_done);
 389      $interface_macro = 'XSINTERFACE_FUNC' ;
 390      $interface_macro_set = 'XSINTERFACE_FUNC_SET' ;
 391      $ProtoThisXSUB = $WantPrototypes ;
 392      $ScopeThisXSUB = 0;
 393      $xsreturn = 0;
 394  
 395      $_ = shift(@line);
 396      while (my $kwd = check_keyword("REQUIRE|PROTOTYPES|FALLBACK|VERSIONCHECK|INCLUDE")) {
 397        &{"$kwd}_handler"}() ;
 398        next PARAGRAPH unless @line ;
 399        $_ = shift(@line);
 400      }
 401  
 402      if (check_keyword("BOOT")) {
 403        &check_cpp;
 404        push (@BootCode, "#line $line_no[@line_no - @line] \"$filepathname\"")
 405      if $WantLineNumbers && $line[0] !~ /^\s*#\s*line\b/;
 406        push (@BootCode, @line, "") ;
 407        next PARAGRAPH ;
 408      }
 409  
 410  
 411      # extract return type, function name and arguments
 412      ($ret_type) = TidyType($_);
 413      $RETVAL_no_return = 1 if $ret_type =~ s/^NO_OUTPUT\s+//;
 414  
 415      # Allow one-line ANSI-like declaration
 416      unshift @line, $2
 417        if $process_argtypes
 418      and $ret_type =~ s/^(.*?\w.*?)\s*\b(\w+\s*\(.*)/$1/s;
 419  
 420      # a function definition needs at least 2 lines
 421      blurt ("Error: Function definition too short '$ret_type'"), next PARAGRAPH
 422        unless @line ;
 423  
 424      $externC = 1 if $ret_type =~ s/^extern "C"\s+//;
 425      $static  = 1 if $ret_type =~ s/^static\s+//;
 426  
 427      $func_header = shift(@line);
 428      blurt ("Error: Cannot parse function definition from '$func_header'"), next PARAGRAPH
 429        unless $func_header =~ /^(?:([\w:]*)::)?(\w+)\s*\(\s*(.*?)\s*\)\s*(const)?\s*(;\s*)?$/s;
 430  
 431      ($class, $func_name, $orig_args) =  ($1, $2, $3) ;
 432      $class = "$4 $class" if $4;
 433      ($pname = $func_name) =~ s/^($Prefix)?/$Packprefix/;
 434      ($clean_func_name = $func_name) =~ s/^$Prefix//;
 435      $Full_func_name = "$Packid}_$clean_func_name";
 436      if ($Is_VMS) {
 437        $Full_func_name = $SymSet->addsym($Full_func_name);
 438      }
 439  
 440      # Check for duplicate function definition
 441      for my $tmp (@XSStack) {
 442        next unless defined $tmp->{functions}{$Full_func_name};
 443        Warn("Warning: duplicate function definition '$clean_func_name' detected");
 444        last;
 445      }
 446      $XSStack[$XSS_work_idx]{functions}{$Full_func_name} ++ ;
 447      %XsubAliases = %XsubAliasValues = %Interfaces = @Attributes = ();
 448      $DoSetMagic = 1;
 449  
 450      $orig_args =~ s/\\\s*/ /g;    # process line continuations
 451      my @args;
 452  
 453      my %only_C_inlist;        # Not in the signature of Perl function
 454      if ($process_argtypes and $orig_args =~ /\S/) {
 455        my $args = "$orig_args ,";
 456        if ($args =~ /^( (??{ $C_arg }) , )* $ /x) {
 457      @args = ($args =~ /\G ( (??{ $C_arg }) ) , /xg);
 458      for ( @args ) {
 459        s/^\s+//;
 460        s/\s+$//;
 461        my ($arg, $default) = / ( [^=]* ) ( (?: = .* )? ) /x;
 462        my ($pre, $name) = ($arg =~ /(.*?) \s*
 463                           \b ( \w+ | length\( \s*\w+\s* \) )
 464                           \s* $ /x);
 465        next unless defined($pre) && length($pre);
 466        my $out_type = '';
 467        my $inout_var;
 468        if ($process_inout and s/^(IN|IN_OUTLIST|OUTLIST|OUT|IN_OUT)\s+//) {
 469          my $type = $1;
 470          $out_type = $type if $type ne 'IN';
 471          $arg =~ s/^(IN|IN_OUTLIST|OUTLIST|OUT|IN_OUT)\s+//;
 472          $pre =~ s/^(IN|IN_OUTLIST|OUTLIST|OUT|IN_OUT)\s+//;
 473        }
 474        my $islength;
 475        if ($name =~ /^length\( \s* (\w+) \s* \)\z/x) {
 476          $name = "XSauto_length_of_$1";
 477          $islength = 1;
 478          die "Default value on length() argument: `$_'"
 479            if length $default;
 480        }
 481        if (length $pre or $islength) { # Has a type
 482          if ($islength) {
 483            push @fake_INPUT_pre, $arg;
 484          } else {
 485            push @fake_INPUT, $arg;
 486          }
 487          # warn "pushing '$arg'\n";
 488          $argtype_seen{$name}++;
 489          $_ = "$name$default"; # Assigns to @args
 490        }
 491        $only_C_inlist{$_} = 1 if $out_type eq "OUTLIST" or $islength;
 492        push @outlist, $name if $out_type =~ /OUTLIST$/;
 493        $in_out{$name} = $out_type if $out_type;
 494      }
 495        } else {
 496      @args = split(/\s*,\s*/, $orig_args);
 497      Warn("Warning: cannot parse argument list '$orig_args', fallback to split");
 498        }
 499      } else {
 500        @args = split(/\s*,\s*/, $orig_args);
 501        for (@args) {
 502      if ($process_inout and s/^(IN|IN_OUTLIST|OUTLIST|IN_OUT|OUT)\s+//) {
 503        my $out_type = $1;
 504        next if $out_type eq 'IN';
 505        $only_C_inlist{$_} = 1 if $out_type eq "OUTLIST";
 506        push @outlist, $name if $out_type =~ /OUTLIST$/;
 507        $in_out{$_} = $out_type;
 508      }
 509        }
 510      }
 511      if (defined($class)) {
 512        my $arg0 = ((defined($static) or $func_name eq 'new')
 513            ? "CLASS" : "THIS");
 514        unshift(@args, $arg0);
 515        ($report_args = "$arg0, $report_args") =~ s/^\w+, $/$arg0/;
 516      }
 517      my $extra_args = 0;
 518      @args_num = ();
 519      $num_args = 0;
 520      my $report_args = '';
 521      foreach my $i (0 .. $#args) {
 522        if ($args[$i] =~ s/\.\.\.//) {
 523      $ellipsis = 1;
 524      if ($args[$i] eq '' && $i == $#args) {
 525        $report_args .= ", ...";
 526        pop(@args);
 527        last;
 528      }
 529        }
 530        if ($only_C_inlist{$args[$i]}) {
 531      push @args_num, undef;
 532        } else {
 533      push @args_num, ++$num_args;
 534      $report_args .= ", $args[$i]";
 535        }
 536        if ($args[$i] =~ /^([^=]*[^\s=])\s*=\s*(.*)/s) {
 537      $extra_args++;
 538      $args[$i] = $1;
 539      $defaults{$args[$i]} = $2;
 540      $defaults{$args[$i]} =~ s/"/\\"/g;
 541        }
 542        $proto_arg[$i+1] = '$' ;
 543      }
 544      $min_args = $num_args - $extra_args;
 545      $report_args =~ s/"/\\"/g;
 546      $report_args =~ s/^,\s+//;
 547      my @func_args = @args;
 548      shift @func_args if defined($class);
 549  
 550      for (@func_args) {
 551        s/^/&/ if $in_out{$_};
 552      }
 553      $func_args = join(", ", @func_args);
 554      @args_match{@args} = @args_num;
 555  
 556      $PPCODE = grep(/^\s*PPCODE\s*:/, @line);
 557      $CODE = grep(/^\s*CODE\s*:/, @line);
 558      # Detect CODE: blocks which use ST(n)= or XST_m*(n,v)
 559      #   to set explicit return values.
 560      $EXPLICIT_RETURN = ($CODE &&
 561              ("@line" =~ /(\bST\s*\([^;]*=) | (\bXST_m\w+\s*\()/x ));
 562      $ALIAS  = grep(/^\s*ALIAS\s*:/,  @line);
 563      $INTERFACE  = grep(/^\s*INTERFACE\s*:/,  @line);
 564  
 565      $xsreturn = 1 if $EXPLICIT_RETURN;
 566  
 567      $externC = $externC ? qq[extern "C"] : "";
 568  
 569      # print function header
 570      print Q(<<"EOF");
 571  #$externC
 572  #XS(XS_${Full_func_name}); /* prototype to pass -Wmissing-prototypes */
 573  #XS(XS_${Full_func_name})
 574  #[[
 575  ##ifdef dVAR
 576  #    dVAR; dXSARGS;
 577  ##else
 578  #    dXSARGS;
 579  ##endif
 580  EOF
 581      print Q(<<"EOF") if $ALIAS ;
 582  #    dXSI32;
 583  EOF
 584      print Q(<<"EOF") if $INTERFACE ;
 585  #    dXSFUNCTION($ret_type);
 586  EOF
 587      if ($ellipsis) {
 588        $cond = ($min_args ? qq(items < $min_args) : 0);
 589      } elsif ($min_args == $num_args) {
 590        $cond = qq(items != $min_args);
 591      } else {
 592        $cond = qq(items < $min_args || items > $num_args);
 593      }
 594  
 595      print Q(<<"EOF") if $except;
 596  #    char errbuf[1024];
 597  #    *errbuf = '\0';
 598  EOF
 599  
 600      if ($ALIAS)
 601        { print Q(<<"EOF") if $cond }
 602  #    if ($cond)
 603  #       Perl_croak(aTHX_ "Usage: %s(%s)", GvNAME(CvGV(cv)), "$report_args");
 604  EOF
 605      else
 606        { print Q(<<"EOF") if $cond }
 607  #    if ($cond)
 608  #       Perl_croak(aTHX_ "Usage: %s(%s)", "$pname", "$report_args");
 609  EOF
 610      
 611       # cv doesn't seem to be used, in most cases unless we go in 
 612       # the if of this else
 613       print Q(<<"EOF");
 614  #    PERL_UNUSED_VAR(cv); /* -W */
 615  EOF
 616  
 617      #gcc -Wall: if an xsub has PPCODE is used
 618      #it is possible none of ST, XSRETURN or XSprePUSH macros are used
 619      #hence `ax' (setup by dXSARGS) is unused
 620      #XXX: could breakup the dXSARGS; into dSP;dMARK;dITEMS
 621      #but such a move could break third-party extensions
 622      print Q(<<"EOF") if $PPCODE;
 623  #    PERL_UNUSED_VAR(ax); /* -Wall */
 624  EOF
 625  
 626      print Q(<<"EOF") if $PPCODE;
 627  #    SP -= items;
 628  EOF
 629  
 630      # Now do a block of some sort.
 631  
 632      $condnum = 0;
 633      $cond = '';            # last CASE: condidional
 634      push(@line, "$END:");
 635      push(@line_no, $line_no[-1]);
 636      $_ = '';
 637      &check_cpp;
 638      while (@line) {
 639        &CASE_handler if check_keyword("CASE");
 640        print Q(<<"EOF");
 641  #   $except [[
 642  EOF
 643  
 644        # do initialization of input variables
 645        $thisdone = 0;
 646        $retvaldone = 0;
 647        $deferred = "";
 648        %arg_list = () ;
 649        $gotRETVAL = 0;
 650      
 651        INPUT_handler() ;
 652        process_keyword("INPUT|PREINIT|INTERFACE_MACRO|C_ARGS|ALIAS|ATTRS|PROTOTYPE|SCOPE|OVERLOAD") ;
 653  
 654        print Q(<<"EOF") if $ScopeThisXSUB;
 655  #   ENTER;
 656  #   [[
 657  EOF
 658      
 659        if (!$thisdone && defined($class)) {
 660      if (defined($static) or $func_name eq 'new') {
 661        print "\tchar *";
 662        $var_types{"CLASS"} = "char *";
 663        &generate_init("char *", 1, "CLASS");
 664      }
 665      else {
 666        print "\t$class *";
 667        $var_types{"THIS"} = "$class *";
 668        &generate_init("$class *", 1, "THIS");
 669      }
 670        }
 671        
 672        # do code
 673        if (/^\s*NOT_IMPLEMENTED_YET/) {
 674      print "\n\tPerl_croak(aTHX_ \"$pname: not implemented yet\");\n";
 675      $_ = '' ;
 676        } else {
 677      if ($ret_type ne "void") {
 678        print "\t" . &map_type($ret_type, 'RETVAL') . ";\n"
 679          if !$retvaldone;
 680        $args_match{"RETVAL"} = 0;
 681        $var_types{"RETVAL"} = $ret_type;
 682        print "\tdXSTARG;\n"
 683          if $WantOptimize and $targetable{$type_kind{$ret_type}};
 684      }
 685      
 686      if (@fake_INPUT or @fake_INPUT_pre) {
 687        unshift @line, @fake_INPUT_pre, @fake_INPUT, $_;
 688        $_ = "";
 689        $processing_arg_with_types = 1;
 690        INPUT_handler() ;
 691      }
 692      print $deferred;
 693      
 694          process_keyword("INIT|ALIAS|ATTRS|PROTOTYPE|INTERFACE_MACRO|INTERFACE|C_ARGS|OVERLOAD") ;
 695      
 696      if (check_keyword("PPCODE")) {
 697        print_section();
 698        death ("PPCODE must be last thing") if @line;
 699        print "\tLEAVE;\n" if $ScopeThisXSUB;
 700        print "\tPUTBACK;\n\treturn;\n";
 701      } elsif (check_keyword("CODE")) {
 702        print_section() ;
 703      } elsif (defined($class) and $func_name eq "DESTROY") {
 704        print "\n\t";
 705        print "delete THIS;\n";
 706      } else {
 707        print "\n\t";
 708        if ($ret_type ne "void") {
 709          print "RETVAL = ";
 710          $wantRETVAL = 1;
 711        }
 712        if (defined($static)) {
 713          if ($func_name eq 'new') {
 714            $func_name = "$class";
 715          } else {
 716            print "$class}::";
 717          }
 718        } elsif (defined($class)) {
 719          if ($func_name eq 'new') {
 720            $func_name .= " $class";
 721          } else {
 722            print "THIS->";
 723          }
 724        }
 725        $func_name =~ s/^\Q$args{'s'}//
 726          if exists $args{'s'};
 727        $func_name = 'XSFUNCTION' if $interface;
 728        print "$func_name($func_args);\n";
 729      }
 730        }
 731        
 732        # do output variables
 733        $gotRETVAL = 0;        # 1 if RETVAL seen in OUTPUT section;
 734        undef $RETVAL_code ;    # code to set RETVAL (from OUTPUT section);
 735        # $wantRETVAL set if 'RETVAL =' autogenerated
 736        ($wantRETVAL, $ret_type) = (0, 'void') if $RETVAL_no_return;
 737        undef %outargs ;
 738        process_keyword("POSTCALL|OUTPUT|ALIAS|ATTRS|PROTOTYPE|OVERLOAD");
 739        
 740        &generate_output($var_types{$_}, $args_match{$_}, $_, $DoSetMagic)
 741      for grep $in_out{$_} =~ /OUT$/, keys %in_out;
 742        
 743        # all OUTPUT done, so now push the return value on the stack
 744        if ($gotRETVAL && $RETVAL_code) {
 745      print "\t$RETVAL_code\n";
 746        } elsif ($gotRETVAL || $wantRETVAL) {
 747      my $t = $WantOptimize && $targetable{$type_kind{$ret_type}};
 748      my $var = 'RETVAL';
 749      my $type = $ret_type;
 750      
 751      # 0: type, 1: with_size, 2: how, 3: how_size
 752      if ($t and not $t->[1] and $t->[0] eq 'p') {
 753        # PUSHp corresponds to setpvn.  Treate setpv directly
 754        my $what = eval qq("$t->[2]");
 755        warn $@ if $@;
 756        
 757        print "\tsv_setpv(TARG, $what); XSprePUSH; PUSHTARG;\n";
 758        $prepush_done = 1;
 759      }
 760      elsif ($t) {
 761        my $what = eval qq("$t->[2]");
 762        warn $@ if $@;
 763        
 764        my $size = $t->[3];
 765        $size = '' unless defined $size;
 766        $size = eval qq("$size");
 767        warn $@ if $@;
 768        print "\tXSprePUSH; PUSH$t->[0]($what$size);\n";
 769        $prepush_done = 1;
 770      }
 771      else {
 772        # RETVAL almost never needs SvSETMAGIC()
 773        &generate_output($ret_type, 0, 'RETVAL', 0);
 774      }
 775        }
 776        
 777        $xsreturn = 1 if $ret_type ne "void";
 778        my $num = $xsreturn;
 779        my $c = @outlist;
 780        print "\tXSprePUSH;" if $c and not $prepush_done;
 781        print "\tEXTEND(SP,$c);\n" if $c;
 782        $xsreturn += $c;
 783        generate_output($var_types{$_}, $num++, $_, 0, 1) for @outlist;
 784        
 785        # do cleanup
 786        process_keyword("CLEANUP|ALIAS|ATTRS|PROTOTYPE|OVERLOAD") ;
 787        
 788        print Q(<<"EOF") if $ScopeThisXSUB;
 789  #   ]]
 790  EOF
 791        print Q(<<"EOF") if $ScopeThisXSUB and not $PPCODE;
 792  #   LEAVE;
 793  EOF
 794        
 795        # print function trailer
 796        print Q(<<"EOF");
 797  #    ]]
 798  EOF
 799        print Q(<<"EOF") if $except;
 800  #    BEGHANDLERS
 801  #    CATCHALL
 802  #    sprintf(errbuf, "%s: %s\\tpropagated", Xname, Xreason);
 803  #    ENDHANDLERS
 804  EOF
 805        if (check_keyword("CASE")) {
 806      blurt ("Error: No `CASE:' at top of function")
 807        unless $condnum;
 808      $_ = "CASE: $_";    # Restore CASE: label
 809      next;
 810        }
 811        last if $_ eq "$END:";
 812        death(/^$BLOCK_re/o ? "Misplaced `$1:'" : "Junk at end of function");
 813      }
 814      
 815      print Q(<<"EOF") if $except;
 816  #    if (errbuf[0])
 817  #    Perl_croak(aTHX_ errbuf);
 818  EOF
 819      
 820      if ($xsreturn) {
 821        print Q(<<"EOF") unless $PPCODE;
 822  #    XSRETURN($xsreturn);
 823  EOF
 824      } else {
 825        print Q(<<"EOF") unless $PPCODE;
 826  #    XSRETURN_EMPTY;
 827  EOF
 828      }
 829  
 830      print Q(<<"EOF");
 831  #]]
 832  #
 833  EOF
 834  
 835      my $newXS = "newXS" ;
 836      my $proto = "" ;
 837      
 838      # Build the prototype string for the xsub
 839      if ($ProtoThisXSUB) {
 840        $newXS = "newXSproto";
 841        
 842        if ($ProtoThisXSUB eq 2) {
 843      # User has specified empty prototype
 844        }
 845        elsif ($ProtoThisXSUB eq 1) {
 846      my $s = ';';
 847      if ($min_args < $num_args)  {
 848        $s = '';
 849        $proto_arg[$min_args] .= ";" ;
 850      }
 851      push @proto_arg, "$s\@"
 852        if $ellipsis ;
 853      
 854      $proto = join ("", grep defined, @proto_arg);
 855        }
 856        else {
 857      # User has specified a prototype
 858      $proto = $ProtoThisXSUB;
 859        }
 860        $proto = qq{, "$proto"};
 861      }
 862      
 863      if (%XsubAliases) {
 864        $XsubAliases{$pname} = 0
 865      unless defined $XsubAliases{$pname} ;
 866        while ( ($name, $value) = each %XsubAliases) {
 867      push(@InitFileCode, Q(<<"EOF"));
 868  #        cv = newXS(\"$name\", XS_$Full_func_name, file);
 869  #        XSANY.any_i32 = $value ;
 870  EOF
 871      push(@InitFileCode, Q(<<"EOF")) if $proto;
 872  #        sv_setpv((SV*)cv$proto) ;
 873  EOF
 874        }
 875      }
 876      elsif (@Attributes) {
 877        push(@InitFileCode, Q(<<"EOF"));
 878  #        cv = newXS(\"$pname\", XS_$Full_func_name, file);
 879  #        apply_attrs_string("$Package", cv, "@Attributes", 0);
 880  EOF
 881      }
 882      elsif ($interface) {
 883        while ( ($name, $value) = each %Interfaces) {
 884      $name = "$Package\::$name" unless $name =~ /::/;
 885      push(@InitFileCode, Q(<<"EOF"));
 886  #        cv = newXS(\"$name\", XS_$Full_func_name, file);
 887  #        $interface_macro_set(cv,$value) ;
 888  EOF
 889      push(@InitFileCode, Q(<<"EOF")) if $proto;
 890  #        sv_setpv((SV*)cv$proto) ;
 891  EOF
 892        }
 893      }
 894      else {
 895        push(@InitFileCode,
 896         "        $newXS}(\"$pname\", XS_$Full_func_name, file$proto);\n");
 897      }
 898    }
 899  
 900    if ($Overload) # make it findable with fetchmethod
 901    {
 902      print Q(<<"EOF");
 903  #XS(XS_${Packid}_nil); /* prototype to pass -Wmissing-prototypes */
 904  #XS(XS_${Packid}_nil)
 905  #{
 906  #   XSRETURN_EMPTY;
 907  #}
 908  #
 909  EOF
 910      unshift(@InitFileCode, <<"MAKE_FETCHMETHOD_WORK");
 911      /* Making a sub named "${Package}::()" allows the package */
 912      /* to be findable via fetchmethod(), and causes */
 913      /* overload::Overloaded("${Package}") to return true. */
 914      newXS("$Package}::()", XS_$Packid}_nil, file$proto);
 915  MAKE_FETCHMETHOD_WORK
 916    }
 917  
 918    # print initialization routine
 919  
 920    print Q(<<"EOF");
 921  ##ifdef __cplusplus
 922  #extern "C"
 923  ##endif
 924  EOF
 925  
 926    print Q(<<"EOF");
 927  #XS(boot_$Module_cname); /* prototype to pass -Wmissing-prototypes */
 928  #XS(boot_$Module_cname)
 929  EOF
 930  
 931    print Q(<<"EOF");
 932  #[[
 933  ##ifdef dVAR
 934  #    dVAR; dXSARGS;
 935  ##else
 936  #    dXSARGS;
 937  ##endif
 938  EOF
 939  
 940    #-Wall: if there is no $Full_func_name there are no xsubs in this .xs
 941    #so `file' is unused
 942    print Q(<<"EOF") if $Full_func_name;
 943  #    char* file = __FILE__;
 944  EOF
 945  
 946    print Q("#\n");
 947  
 948    print Q(<<"EOF");
 949  #    PERL_UNUSED_VAR(cv); /* -W */
 950  #    PERL_UNUSED_VAR(items); /* -W */
 951  EOF
 952      
 953    print Q(<<"EOF") if $WantVersionChk ;
 954  #    XS_VERSION_BOOTCHECK ;
 955  #
 956  EOF
 957  
 958    print Q(<<"EOF") if defined $XsubAliases or defined $Interfaces ;
 959  #    {
 960  #        CV * cv ;
 961  #
 962  EOF
 963  
 964    print Q(<<"EOF") if ($Overload);
 965  #    /* register the overloading (type 'A') magic */
 966  #    PL_amagic_generation++;
 967  #    /* The magic for overload gets a GV* via gv_fetchmeth as */
 968  #    /* mentioned above, and looks in the SV* slot of it for */
 969  #    /* the "fallback" status. */
 970  #    sv_setsv(
 971  #        get_sv( "${Package}::()", TRUE ),
 972  #        $Fallback
 973  #    );
 974  EOF
 975  
 976    print @InitFileCode;
 977  
 978    print Q(<<"EOF") if defined $XsubAliases or defined $Interfaces ;
 979  #    }
 980  EOF
 981  
 982    if (@BootCode)
 983    {
 984      print "\n    /* Initialisation Section */\n\n" ;
 985      @line = @BootCode;
 986      print_section();
 987      print "\n    /* End of Initialisation Section */\n\n" ;
 988    }
 989  
 990    if ($] >= 5.009) {
 991      print <<'EOF';
 992      if (PL_unitcheckav)
 993           call_list(PL_scopestack_ix, PL_unitcheckav);
 994  EOF
 995    }
 996  
 997    print Q(<<"EOF");
 998  #    XSRETURN_YES;
 999  #]]
1000  #
1001  EOF
1002  
1003    warn("Please specify prototyping behavior for $filename (see perlxs manual)\n")
1004      unless $ProtoUsed ;
1005  
1006    chdir($orig_cwd);
1007    select($orig_fh);
1008    untie *PSEUDO_STDOUT if tied *PSEUDO_STDOUT;
1009    close $FH;
1010  
1011    return 1;
1012  }
1013  
1014  sub errors { $errors }
1015  
1016  sub standard_typemap_locations {
1017    # Add all the default typemap locations to the search path
1018    my @tm = qw(typemap);
1019    
1020    my $updir = File::Spec->updir;
1021    foreach my $dir (File::Spec->catdir(($updir) x 1), File::Spec->catdir(($updir) x 2),
1022             File::Spec->catdir(($updir) x 3), File::Spec->catdir(($updir) x 4)) {
1023      
1024      unshift @tm, File::Spec->catfile($dir, 'typemap');
1025      unshift @tm, File::Spec->catfile($dir, lib => ExtUtils => 'typemap');
1026    }
1027    foreach my $dir (@INC) {
1028      my $file = File::Spec->catfile($dir, ExtUtils => 'typemap');
1029      unshift @tm, $file if -e $file;
1030    }
1031    return @tm;
1032  }
1033    
1034  sub TrimWhitespace
1035  {
1036    $_[0] =~ s/^\s+|\s+$//go ;
1037  }
1038  
1039  sub TidyType
1040    {
1041      local ($_) = @_ ;
1042  
1043      # rationalise any '*' by joining them into bunches and removing whitespace
1044      s#\s*(\*+)\s*#$1#g;
1045      s#(\*+)# $1 #g ;
1046  
1047      # change multiple whitespace into a single space
1048      s/\s+/ /g ;
1049  
1050      # trim leading & trailing whitespace
1051      TrimWhitespace($_) ;
1052  
1053      $_ ;
1054  }
1055  
1056  # Input:  ($_, @line) == unparsed input.
1057  # Output: ($_, @line) == (rest of line, following lines).
1058  # Return: the matched keyword if found, otherwise 0
1059  sub check_keyword {
1060      $_ = shift(@line) while !/\S/ && @line;
1061      s/^(\s*)($_[0])\s*:\s*(?:#.*)?/$1/s && $2;
1062  }
1063  
1064  sub print_section {
1065      # the "do" is required for right semantics
1066      do { $_ = shift(@line) } while !/\S/ && @line;
1067  
1068      print("#line ", $line_no[@line_no - @line -1], " \"$filepathname\"\n")
1069      if $WantLineNumbers && !/^\s*#\s*line\b/ && !/^#if XSubPPtmp/;
1070      for (;  defined($_) && !/^$BLOCK_re/o;  $_ = shift(@line)) {
1071      print "$_\n";
1072      }
1073      print 'ExtUtils::ParseXS::CountLines'->end_marker, "\n" if $WantLineNumbers;
1074  }
1075  
1076  sub merge_section {
1077      my $in = '';
1078  
1079      while (!/\S/ && @line) {
1080        $_ = shift(@line);
1081      }
1082  
1083      for (;  defined($_) && !/^$BLOCK_re/o;  $_ = shift(@line)) {
1084        $in .= "$_\n";
1085      }
1086      chomp $in;
1087      return $in;
1088    }
1089  
1090  sub process_keyword($)
1091    {
1092      my($pattern) = @_ ;
1093      my $kwd ;
1094  
1095      &{"$kwd}_handler"}()
1096        while $kwd = check_keyword($pattern) ;
1097    }
1098  
1099  sub CASE_handler {
1100    blurt ("Error: `CASE:' after unconditional `CASE:'")
1101      if $condnum && $cond eq '';
1102    $cond = $_;
1103    TrimWhitespace($cond);
1104    print "   ", ($condnum++ ? " else" : ""), ($cond ? " if ($cond)\n" : "\n");
1105    $_ = '' ;
1106  }
1107  
1108  sub INPUT_handler {
1109    for (;  !/^$BLOCK_re/o;  $_ = shift(@line)) {
1110      last if /^\s*NOT_IMPLEMENTED_YET/;
1111      next unless /\S/;        # skip blank lines
1112  
1113      TrimWhitespace($_) ;
1114      my $line = $_ ;
1115  
1116      # remove trailing semicolon if no initialisation
1117      s/\s*;$//g unless /[=;+].*\S/ ;
1118  
1119      # Process the length(foo) declarations
1120      if (s/^([^=]*)\blength\(\s*(\w+)\s*\)\s*$/$1 XSauto_length_of_$2=NO_INIT/x) {
1121        print "\tSTRLEN\tSTRLEN_length_of_$2;\n";
1122        $lengthof{$2} = $name;
1123        # $islengthof{$name} = $1;
1124        $deferred .= "\n\tXSauto_length_of_$2 = STRLEN_length_of_$2;";
1125      }
1126  
1127      # check for optional initialisation code
1128      my $var_init = '' ;
1129      $var_init = $1 if s/\s*([=;+].*)$//s ;
1130      $var_init =~ s/"/\\"/g;
1131  
1132      s/\s+/ /g;
1133      my ($var_type, $var_addr, $var_name) = /^(.*?[^&\s])\s*(\&?)\s*\b(\w+)$/s
1134        or blurt("Error: invalid argument declaration '$line'"), next;
1135  
1136      # Check for duplicate definitions
1137      blurt ("Error: duplicate definition of argument '$var_name' ignored"), next
1138        if $arg_list{$var_name}++
1139      or defined $argtype_seen{$var_name} and not $processing_arg_with_types;
1140  
1141      $thisdone |= $var_name eq "THIS";
1142      $retvaldone |= $var_name eq "RETVAL";
1143      $var_types{$var_name} = $var_type;
1144      # XXXX This check is a safeguard against the unfinished conversion of
1145      # generate_init().  When generate_init() is fixed,
1146      # one can use 2-args map_type() unconditionally.
1147      if ($var_type =~ / \( \s* \* \s* \) /x) {
1148        # Function pointers are not yet supported with &output_init!
1149        print "\t" . &map_type($var_type, $var_name);
1150        $name_printed = 1;
1151      } else {
1152        print "\t" . &map_type($var_type);
1153        $name_printed = 0;
1154      }
1155      $var_num = $args_match{$var_name};
1156  
1157      $proto_arg[$var_num] = ProtoString($var_type)
1158        if $var_num ;
1159      $func_args =~ s/\b($var_name)\b/&$1/ if $var_addr;
1160      if ($var_init =~ /^[=;]\s*NO_INIT\s*;?\s*$/
1161      or $in_out{$var_name} and $in_out{$var_name} =~ /^OUT/
1162      and $var_init !~ /\S/) {
1163        if ($name_printed) {
1164      print ";\n";
1165        } else {
1166      print "\t$var_name;\n";
1167        }
1168      } elsif ($var_init =~ /\S/) {
1169        &output_init($var_type, $var_num, $var_name, $var_init, $name_printed);
1170      } elsif ($var_num) {
1171        # generate initialization code
1172        &generate_init($var_type, $var_num, $var_name, $name_printed);
1173      } else {
1174        print ";\n";
1175      }
1176    }
1177  }
1178  
1179  sub OUTPUT_handler {
1180    for (;  !/^$BLOCK_re/o;  $_ = shift(@line)) {
1181      next unless /\S/;
1182      if (/^\s*SETMAGIC\s*:\s*(ENABLE|DISABLE)\s*/) {
1183        $DoSetMagic = ($1 eq "ENABLE" ? 1 : 0);
1184        next;
1185      }
1186      my ($outarg, $outcode) = /^\s*(\S+)\s*(.*?)\s*$/s ;
1187      blurt ("Error: duplicate OUTPUT argument '$outarg' ignored"), next
1188        if $outargs{$outarg} ++ ;
1189      if (!$gotRETVAL and $outarg eq 'RETVAL') {
1190        # deal with RETVAL last
1191        $RETVAL_code = $outcode ;
1192        $gotRETVAL = 1 ;
1193        next ;
1194      }
1195      blurt ("Error: OUTPUT $outarg not an argument"), next
1196        unless defined($args_match{$outarg});
1197      blurt("Error: No input definition for OUTPUT argument '$outarg' - ignored"), next
1198        unless defined $var_types{$outarg} ;
1199      $var_num = $args_match{$outarg};
1200      if ($outcode) {
1201        print "\t$outcode\n";
1202        print "\tSvSETMAGIC(ST(" , $var_num-1 , "));\n" if $DoSetMagic;
1203      } else {
1204        &generate_output($var_types{$outarg}, $var_num, $outarg, $DoSetMagic);
1205      }
1206      delete $in_out{$outarg}     # No need to auto-OUTPUT
1207        if exists $in_out{$outarg} and $in_out{$outarg} =~ /OUT$/;
1208    }
1209  }
1210  
1211  sub C_ARGS_handler() {
1212    my $in = merge_section();
1213  
1214    TrimWhitespace($in);
1215    $func_args = $in;
1216  }
1217  
1218  sub INTERFACE_MACRO_handler() {
1219    my $in = merge_section();
1220  
1221    TrimWhitespace($in);
1222    if ($in =~ /\s/) {        # two
1223      ($interface_macro, $interface_macro_set) = split ' ', $in;
1224    } else {
1225      $interface_macro = $in;
1226      $interface_macro_set = 'UNKNOWN_CVT'; # catch later
1227    }
1228    $interface = 1;        # local
1229    $Interfaces = 1;        # global
1230  }
1231  
1232  sub INTERFACE_handler() {
1233    my $in = merge_section();
1234  
1235    TrimWhitespace($in);
1236  
1237    foreach (split /[\s,]+/, $in) {
1238      my $name = $_;
1239      $name =~ s/^$Prefix//;
1240      $Interfaces{$name} = $_;
1241    }
1242    print Q(<<"EOF");
1243  #    XSFUNCTION = $interface_macro($ret_type,cv,XSANY.any_dptr);
1244  EOF
1245    $interface = 1;        # local
1246    $Interfaces = 1;        # global
1247  }
1248  
1249  sub CLEANUP_handler() { print_section() }
1250  sub PREINIT_handler() { print_section() }
1251  sub POSTCALL_handler() { print_section() }
1252  sub INIT_handler()    { print_section() }
1253  
1254  sub GetAliases
1255    {
1256      my ($line) = @_ ;
1257      my ($orig) = $line ;
1258      my ($alias) ;
1259      my ($value) ;
1260  
1261      # Parse alias definitions
1262      # format is
1263      #    alias = value alias = value ...
1264  
1265      while ($line =~ s/^\s*([\w:]+)\s*=\s*(\w+)\s*//) {
1266        $alias = $1 ;
1267        $orig_alias = $alias ;
1268        $value = $2 ;
1269  
1270        # check for optional package definition in the alias
1271        $alias = $Packprefix . $alias if $alias !~ /::/ ;
1272  
1273        # check for duplicate alias name & duplicate value
1274        Warn("Warning: Ignoring duplicate alias '$orig_alias'")
1275      if defined $XsubAliases{$alias} ;
1276  
1277        Warn("Warning: Aliases '$orig_alias' and '$XsubAliasValues{$value}' have identical values")
1278      if $XsubAliasValues{$value} ;
1279  
1280        $XsubAliases = 1;
1281        $XsubAliases{$alias} = $value ;
1282        $XsubAliasValues{$value} = $orig_alias ;
1283      }
1284  
1285      blurt("Error: Cannot parse ALIAS definitions from '$orig'")
1286        if $line ;
1287    }
1288  
1289  sub ATTRS_handler ()
1290    {
1291      for (;  !/^$BLOCK_re/o;  $_ = shift(@line)) {
1292        next unless /\S/;
1293        TrimWhitespace($_) ;
1294        push @Attributes, $_;
1295      }
1296    }
1297  
1298  sub ALIAS_handler ()
1299    {
1300      for (;  !/^$BLOCK_re/o;  $_ = shift(@line)) {
1301        next unless /\S/;
1302        TrimWhitespace($_) ;
1303        GetAliases($_) if $_ ;
1304      }
1305    }
1306  
1307  sub OVERLOAD_handler()
1308  {
1309    for (;  !/^$BLOCK_re/o;  $_ = shift(@line)) {
1310      next unless /\S/;
1311      TrimWhitespace($_) ;
1312      while ( s/^\s*([\w:"\\)\+\-\*\/\%\<\>\.\&\|\^\!\~\{\}\=]+)\s*//) {
1313        $Overload = 1 unless $Overload;
1314        my $overload = "$Package\::(".$1 ;
1315        push(@InitFileCode,
1316         "        newXS(\"$overload\", XS_$Full_func_name, file$proto);\n");
1317      }
1318    }  
1319  }
1320  
1321  sub FALLBACK_handler()
1322  {
1323    # the rest of the current line should contain either TRUE, 
1324    # FALSE or UNDEF
1325    
1326    TrimWhitespace($_) ;
1327    my %map = (
1328           TRUE => "PL_sv_yes", 1 => "PL_sv_yes",
1329           FALSE => "PL_sv_no", 0 => "PL_sv_no",
1330           UNDEF => "PL_sv_undef",
1331          ) ;
1332    
1333    # check for valid FALLBACK value
1334    death ("Error: FALLBACK: TRUE/FALSE/UNDEF") unless exists $map{uc $_} ;
1335    
1336    $Fallback = $map{uc $_} ;
1337  }
1338  
1339  
1340  sub REQUIRE_handler ()
1341    {
1342      # the rest of the current line should contain a version number
1343      my ($Ver) = $_ ;
1344  
1345      TrimWhitespace($Ver) ;
1346  
1347      death ("Error: REQUIRE expects a version number")
1348        unless $Ver ;
1349  
1350      # check that the version number is of the form n.n
1351      death ("Error: REQUIRE: expected a number, got '$Ver'")
1352        unless $Ver =~ /^\d+(\.\d*)?/ ;
1353  
1354      death ("Error: xsubpp $Ver (or better) required--this is only $VERSION.")
1355        unless $VERSION >= $Ver ;
1356    }
1357  
1358  sub VERSIONCHECK_handler ()
1359    {
1360      # the rest of the current line should contain either ENABLE or
1361      # DISABLE
1362  
1363      TrimWhitespace($_) ;
1364  
1365      # check for ENABLE/DISABLE
1366      death ("Error: VERSIONCHECK: ENABLE/DISABLE")
1367        unless /^(ENABLE|DISABLE)/i ;
1368  
1369      $WantVersionChk = 1 if $1 eq 'ENABLE' ;
1370      $WantVersionChk = 0 if $1 eq 'DISABLE' ;
1371  
1372    }
1373  
1374  sub PROTOTYPE_handler ()
1375    {
1376      my $specified ;
1377  
1378      death("Error: Only 1 PROTOTYPE definition allowed per xsub")
1379        if $proto_in_this_xsub ++ ;
1380  
1381      for (;  !/^$BLOCK_re/o;  $_ = shift(@line)) {
1382        next unless /\S/;
1383        $specified = 1 ;
1384        TrimWhitespace($_) ;
1385        if ($_ eq 'DISABLE') {
1386      $ProtoThisXSUB = 0
1387        } elsif ($_ eq 'ENABLE') {
1388      $ProtoThisXSUB = 1
1389        } else {
1390      # remove any whitespace
1391      s/\s+//g ;
1392      death("Error: Invalid prototype '$_'")
1393        unless ValidProtoString($_) ;
1394      $ProtoThisXSUB = C_string($_) ;
1395        }
1396      }
1397  
1398      # If no prototype specified, then assume empty prototype ""
1399      $ProtoThisXSUB = 2 unless $specified ;
1400  
1401      $ProtoUsed = 1 ;
1402  
1403    }
1404  
1405  sub SCOPE_handler ()
1406    {
1407      death("Error: Only 1 SCOPE declaration allowed per xsub")
1408        if $scope_in_this_xsub ++ ;
1409  
1410      for (;  !/^$BLOCK_re/o;  $_ = shift(@line)) {
1411        next unless /\S/;
1412        TrimWhitespace($_) ;
1413        if ($_ =~ /^DISABLE/i) {
1414      $ScopeThisXSUB = 0
1415        } elsif ($_ =~ /^ENABLE/i) {
1416      $ScopeThisXSUB = 1
1417        }
1418      }
1419  
1420    }
1421  
1422  sub PROTOTYPES_handler ()
1423    {
1424      # the rest of the current line should contain either ENABLE or
1425      # DISABLE
1426  
1427      TrimWhitespace($_) ;
1428  
1429      # check for ENABLE/DISABLE
1430      death ("Error: PROTOTYPES: ENABLE/DISABLE")
1431        unless /^(ENABLE|DISABLE)/i ;
1432  
1433      $WantPrototypes = 1 if $1 eq 'ENABLE' ;
1434      $WantPrototypes = 0 if $1 eq 'DISABLE' ;
1435      $ProtoUsed = 1 ;
1436  
1437    }
1438  
1439  sub INCLUDE_handler ()
1440    {
1441      # the rest of the current line should contain a valid filename
1442  
1443      TrimWhitespace($_) ;
1444  
1445      death("INCLUDE: filename missing")
1446        unless $_ ;
1447  
1448      death("INCLUDE: output pipe is illegal")
1449        if /^\s*\|/ ;
1450  
1451      # simple minded recursion detector
1452      death("INCLUDE loop detected")
1453        if $IncludedFiles{$_} ;
1454  
1455      ++ $IncludedFiles{$_} unless /\|\s*$/ ;
1456  
1457      # Save the current file context.
1458      push(@XSStack, {
1459              type        => 'file',
1460              LastLine        => $lastline,
1461              LastLineNo      => $lastline_no,
1462              Line            => \@line,
1463              LineNo          => \@line_no,
1464              Filename        => $filename,
1465              Filepathname    => $filepathname,
1466              Handle          => $FH,
1467             }) ;
1468  
1469      $FH = Symbol::gensym();
1470  
1471      # open the new file
1472      open ($FH, "$_") or death("Cannot open '$_': $!") ;
1473  
1474      print Q(<<"EOF");
1475  #
1476  #/* INCLUDE:  Including '$_' from '$filename' */
1477  #
1478  EOF
1479  
1480      $filepathname = $filename = $_ ;
1481  
1482      # Prime the pump by reading the first
1483      # non-blank line
1484  
1485      # skip leading blank lines
1486      while (<$FH>) {
1487        last unless /^\s*$/ ;
1488      }
1489  
1490      $lastline = $_ ;
1491      $lastline_no = $. ;
1492  
1493    }
1494  
1495  sub PopFile()
1496    {
1497      return 0 unless $XSStack[-1]{type} eq 'file' ;
1498  
1499      my $data     = pop @XSStack ;
1500      my $ThisFile = $filename ;
1501      my $isPipe   = ($filename =~ /\|\s*$/) ;
1502  
1503      -- $IncludedFiles{$filename}
1504        unless $isPipe ;
1505  
1506      close $FH ;
1507  
1508      $FH         = $data->{Handle} ;
1509      # $filename is the leafname, which for some reason isused for diagnostic
1510      # messages, whereas $filepathname is the full pathname, and is used for
1511      # #line directives.
1512      $filename   = $data->{Filename} ;
1513      $filepathname = $data->{Filepathname} ;
1514      $lastline   = $data->{LastLine} ;
1515      $lastline_no = $data->{LastLineNo} ;
1516      @line       = @{ $data->{Line} } ;
1517      @line_no    = @{ $data->{LineNo} } ;
1518  
1519      if ($isPipe and $? ) {
1520        -- $lastline_no ;
1521        print STDERR "Error reading from pipe '$ThisFile': $! in $filename, line $lastline_no\n"  ;
1522        exit 1 ;
1523      }
1524  
1525      print Q(<<"EOF");
1526  #
1527  #/* INCLUDE: Returning to '$filename' from '$ThisFile' */
1528  #
1529  EOF
1530  
1531      return 1 ;
1532    }
1533  
1534  sub ValidProtoString ($)
1535    {
1536      my($string) = @_ ;
1537  
1538      if ( $string =~ /^$proto_re+$/ ) {
1539        return $string ;
1540      }
1541  
1542      return 0 ;
1543    }
1544  
1545  sub C_string ($)
1546    {
1547      my($string) = @_ ;
1548  
1549      $string =~ s[\\][\\\\]g ;
1550      $string ;
1551    }
1552  
1553  sub ProtoString ($)
1554    {
1555      my ($type) = @_ ;
1556  
1557      $proto_letter{$type} or "\$" ;
1558    }
1559  
1560  sub check_cpp {
1561    my @cpp = grep(/^\#\s*(?:if|e\w+)/, @line);
1562    if (@cpp) {
1563      my ($cpp, $cpplevel);
1564      for $cpp (@cpp) {
1565        if ($cpp =~ /^\#\s*if/) {
1566      $cpplevel++;
1567        } elsif (!$cpplevel) {
1568      Warn("Warning: #else/elif/endif without #if in this function");
1569      print STDERR "    (precede it with a blank line if the matching #if is outside the function)\n"
1570        if $XSStack[-1]{type} eq 'if';
1571      return;
1572        } elsif ($cpp =~ /^\#\s*endif/) {
1573      $cpplevel--;
1574        }
1575      }
1576      Warn("Warning: #if without #endif in this function") if $cpplevel;
1577    }
1578  }
1579  
1580  
1581  sub Q {
1582    my($text) = @_;
1583    $text =~ s/^#//gm;
1584    $text =~ s/\[\[/{/g;
1585    $text =~ s/\]\]/}/g;
1586    $text;
1587  }
1588  
1589  # Read next xsub into @line from ($lastline, <$FH>).
1590  sub fetch_para {
1591    # parse paragraph
1592    death ("Error: Unterminated `#if/#ifdef/#ifndef'")
1593      if !defined $lastline && $XSStack[-1]{type} eq 'if';
1594    @line = ();
1595    @line_no = () ;
1596    return PopFile() if !defined $lastline;
1597  
1598    if ($lastline =~
1599        /^MODULE\s*=\s*([\w:]+)(?:\s+PACKAGE\s*=\s*([\w:]+))?(?:\s+PREFIX\s*=\s*(\S+))?\s*$/) {
1600      $Module = $1;
1601      $Package = defined($2) ? $2 : ''; # keep -w happy
1602      $Prefix  = defined($3) ? $3 : ''; # keep -w happy
1603      $Prefix = quotemeta $Prefix ;
1604      ($Module_cname = $Module) =~ s/\W/_/g;
1605      ($Packid = $Package) =~ tr/:/_/;
1606      $Packprefix = $Package;
1607      $Packprefix .= "::" if $Packprefix ne "";
1608      $lastline = "";
1609    }
1610  
1611    for (;;) {
1612      # Skip embedded PODs
1613      while ($lastline =~ /^=/) {
1614        while ($lastline = <$FH>) {
1615      last if ($lastline =~ /^=cut\s*$/);
1616        }
1617        death ("Error: Unterminated pod") unless $lastline;
1618        $lastline = <$FH>;
1619        chomp $lastline;
1620        $lastline =~ s/^\s+$//;
1621      }
1622      if ($lastline !~ /^\s*#/ ||
1623      # CPP directives:
1624      #    ANSI:    if ifdef ifndef elif else endif define undef
1625      #        line error pragma
1626      #    gcc:    warning include_next
1627      #   obj-c:    import
1628      #   others:    ident (gcc notes that some cpps have this one)
1629      $lastline =~ /^#[ \t]*(?:(?:if|ifn?def|elif|else|endif|define|undef|pragma|error|warning|line\s+\d+|ident)\b|(?:include(?:_next)?|import)\s*["<].*[>"])/) {
1630        last if $lastline =~ /^\S/ && @line && $line[-1] eq "";
1631        push(@line, $lastline);
1632        push(@line_no, $lastline_no) ;
1633      }
1634  
1635      # Read next line and continuation lines
1636      last unless defined($lastline = <$FH>);
1637      $lastline_no = $.;
1638      my $tmp_line;
1639      $lastline .= $tmp_line
1640        while ($lastline =~ /\\$/ && defined($tmp_line = <$FH>));
1641  
1642      chomp $lastline;
1643      $lastline =~ s/^\s+$//;
1644    }
1645    pop(@line), pop(@line_no) while @line && $line[-1] eq "";
1646    1;
1647  }
1648  
1649  sub output_init {
1650    local($type, $num, $var, $init, $name_printed) = @_;
1651    local($arg) = "ST(" . ($num - 1) . ")";
1652  
1653    if (  $init =~ /^=/  ) {
1654      if ($name_printed) {
1655        eval qq/print " $init\\n"/;
1656      } else {
1657        eval qq/print "\\t$var $init\\n"/;
1658      }
1659      warn $@   if  $@;
1660    } else {
1661      if (  $init =~ s/^\+//  &&  $num  ) {
1662        &generate_init($type, $num, $var, $name_printed);
1663      } elsif ($name_printed) {
1664        print ";\n";
1665        $init =~ s/^;//;
1666      } else {
1667        eval qq/print "\\t$var;\\n"/;
1668        warn $@   if  $@;
1669        $init =~ s/^;//;
1670      }
1671      $deferred .= eval qq/"\\n\\t$init\\n"/;
1672      warn $@   if  $@;
1673    }
1674  }
1675  
1676  sub Warn
1677    {
1678      # work out the line number
1679      my $line_no = $line_no[@line_no - @line -1] ;
1680  
1681      print STDERR "@_ in $filename, line $line_no\n" ;
1682    }
1683  
1684  sub blurt
1685    {
1686      Warn @_ ;
1687      $errors ++
1688    }
1689  
1690  sub death
1691    {
1692      Warn @_ ;
1693      exit 1 ;
1694    }
1695  
1696  sub generate_init {
1697    local($type, $num, $var) = @_;
1698    local($arg) = "ST(" . ($num - 1) . ")";
1699    local($argoff) = $num - 1;
1700    local($ntype);
1701    local($tk);
1702  
1703    $type = TidyType($type) ;
1704    blurt("Error: '$type' not in typemap"), return
1705      unless defined($type_kind{$type});
1706  
1707    ($ntype = $type) =~ s/\s*\*/Ptr/g;
1708    ($subtype = $ntype) =~ s/(?:Array)?(?:Ptr)?$//;
1709    $tk = $type_kind{$type};
1710    $tk =~ s/OBJ$/REF/ if $func_name =~ /DESTROY$/;
1711    if ($tk eq 'T_PV' and exists $lengthof{$var}) {
1712      print "\t$var" unless $name_printed;
1713      print " = ($type)SvPV($arg, STRLEN_length_of_$var);\n";
1714      die "default value not supported with length(NAME) supplied"
1715        if defined $defaults{$var};
1716      return;
1717    }
1718    $type =~ tr/:/_/ unless $hiertype;
1719    blurt("Error: No INPUT definition for type '$type', typekind '$type_kind{$type}' found"), return
1720      unless defined $input_expr{$tk} ;
1721    $expr = $input_expr{$tk};
1722    if ($expr =~ /DO_ARRAY_ELEM/) {
1723      blurt("Error: '$subtype' not in typemap"), return
1724        unless defined($type_kind{$subtype});
1725      blurt("Error: No INPUT definition for type '$subtype', typekind '$type_kind{$subtype}' found"), return
1726        unless defined $input_expr{$type_kind{$subtype}} ;
1727      $subexpr = $input_expr{$type_kind{$subtype}};
1728      $subexpr =~ s/\$type/\$subtype/g;
1729      $subexpr =~ s/ntype/subtype/g;
1730      $subexpr =~ s/\$arg/ST(ix_$var)/g;
1731      $subexpr =~ s/\n\t/\n\t\t/g;
1732      $subexpr =~ s/is not of (.*\")/[arg %d] is not of $1, ix_$var + 1/g;
1733      $subexpr =~ s/\$var/$var}[ix_$var - $argoff]/;
1734      $expr =~ s/DO_ARRAY_ELEM/$subexpr/;
1735    }
1736    if ($expr =~ m#/\*.*scope.*\*/#i) {  # "scope" in C comments
1737      $ScopeThisXSUB = 1;
1738    }
1739    if (defined($defaults{$var})) {
1740      $expr =~ s/(\t+)/$1    /g;
1741      $expr =~ s/        /\t/g;
1742      if ($name_printed) {
1743        print ";\n";
1744      } else {
1745        eval qq/print "\\t$var;\\n"/;
1746        warn $@   if  $@;
1747      }
1748      if ($defaults{$var} eq 'NO_INIT') {
1749        $deferred .= eval qq/"\\n\\tif (items >= $num) {\\n$expr;\\n\\t}\\n"/;
1750      } else {
1751        $deferred .= eval qq/"\\n\\tif (items < $num)\\n\\t    $var = $defaults{$var};\\n\\telse {\\n$expr;\\n\\t}\\n"/;
1752      }
1753      warn $@   if  $@;
1754    } elsif ($ScopeThisXSUB or $expr !~ /^\s*\$var =/) {
1755      if ($name_printed) {
1756        print ";\n";
1757      } else {
1758        eval qq/print "\\t$var;\\n"/;
1759        warn $@   if  $@;
1760      }
1761      $deferred .= eval qq/"\\n$expr;\\n"/;
1762      warn $@   if  $@;
1763    } else {
1764      die "panic: do not know how to handle this branch for function pointers"
1765        if $name_printed;
1766      eval qq/print "$expr;\\n"/;
1767      warn $@   if  $@;
1768    }
1769  }
1770  
1771  sub generate_output {
1772    local($type, $num, $var, $do_setmagic, $do_push) = @_;
1773    local($arg) = "ST(" . ($num - ($num != 0)) . ")";
1774    local($argoff) = $num - 1;
1775    local($ntype);
1776  
1777    $type = TidyType($type) ;
1778    if ($type =~ /^array\(([^,]*),(.*)\)/) {
1779      print "\t$arg = sv_newmortal();\n";
1780      print "\tsv_setpvn($arg, (char *)$var, $2 * sizeof($1));\n";
1781      print "\tSvSETMAGIC($arg);\n" if $do_setmagic;
1782    } else {
1783      blurt("Error: '$type' not in typemap"), return
1784        unless defined($type_kind{$type});
1785      blurt("Error: No OUTPUT definition for type '$type', typekind '$type_kind{$type}' found"), return
1786        unless defined $output_expr{$type_kind{$type}} ;
1787      ($ntype = $type) =~ s/\s*\*/Ptr/g;
1788      $ntype =~ s/\(\)//g;
1789      ($subtype = $ntype) =~ s/(?:Array)?(?:Ptr)?$//;
1790      $expr = $output_expr{$type_kind{$type}};
1791      if ($expr =~ /DO_ARRAY_ELEM/) {
1792        blurt("Error: '$subtype' not in typemap"), return
1793      unless defined($type_kind{$subtype});
1794        blurt("Error: No OUTPUT definition for type '$subtype', typekind '$type_kind{$subtype}' found"), return
1795      unless defined $output_expr{$type_kind{$subtype}} ;
1796        $subexpr = $output_expr{$type_kind{$subtype}};
1797        $subexpr =~ s/ntype/subtype/g;
1798        $subexpr =~ s/\$arg/ST(ix_$var)/g;
1799        $subexpr =~ s/\$var/$var}[ix_$var]/g;
1800        $subexpr =~ s/\n\t/\n\t\t/g;
1801        $expr =~ s/DO_ARRAY_ELEM\n/$subexpr/;
1802        eval "print qq\a$expr\a";
1803        warn $@   if  $@;
1804        print "\t\tSvSETMAGIC(ST(ix_$var));\n" if $do_setmagic;
1805      } elsif ($var eq 'RETVAL') {
1806        if ($expr =~ /^\t\$arg = new/) {
1807      # We expect that $arg has refcnt 1, so we need to
1808      # mortalize it.
1809      eval "print qq\a$expr\a";
1810      warn $@   if  $@;
1811      print "\tsv_2mortal(ST($num));\n";
1812      print "\tSvSETMAGIC(ST($num));\n" if $do_setmagic;
1813        } elsif ($expr =~ /^\s*\$arg\s*=/) {
1814      # We expect that $arg has refcnt >=1, so we need
1815      # to mortalize it!
1816      eval "print qq\a$expr\a";
1817      warn $@   if  $@;
1818      print "\tsv_2mortal(ST(0));\n";
1819      print "\tSvSETMAGIC(ST(0));\n" if $do_setmagic;
1820        } else {
1821      # Just hope that the entry would safely write it
1822      # over an already mortalized value. By
1823      # coincidence, something like $arg = &sv_undef
1824      # works too.
1825      print "\tST(0) = sv_newmortal();\n";
1826      eval "print qq\a$expr\a";
1827      warn $@   if  $@;
1828      # new mortals don't have set magic
1829        }
1830      } elsif ($do_push) {
1831        print "\tPUSHs(sv_newmortal());\n";
1832        $arg = "ST($num)";
1833        eval "print qq\a$expr\a";
1834        warn $@   if  $@;
1835        print "\tSvSETMAGIC($arg);\n" if $do_setmagic;
1836      } elsif ($arg =~ /^ST\(\d+\)$/) {
1837        eval "print qq\a$expr\a";
1838        warn $@   if  $@;
1839        print "\tSvSETMAGIC($arg);\n" if $do_setmagic;
1840      }
1841    }
1842  }
1843  
1844  sub map_type {
1845    my($type, $varname) = @_;
1846    
1847    # C++ has :: in types too so skip this
1848    $type =~ tr/:/_/ unless $hiertype;
1849    $type =~ s/^array\(([^,]*),(.*)\).*/$1 */s;
1850    if ($varname) {
1851      if ($varname && $type =~ / \( \s* \* (?= \s* \) ) /xg) {
1852        (substr $type, pos $type, 0) = " $varname ";
1853      } else {
1854        $type .= "\t$varname";
1855      }
1856    }
1857    $type;
1858  }
1859  
1860  
1861  #########################################################
1862  package
1863    ExtUtils::ParseXS::CountLines;
1864  use strict;
1865  use vars qw($SECTION_END_MARKER);
1866  
1867  sub TIEHANDLE {
1868    my ($class, $cfile, $fh) = @_;
1869    $cfile =~ s/\\/\\\\/g;
1870    $SECTION_END_MARKER = qq{#line --- "$cfile"};
1871    
1872    return bless {buffer => '',
1873          fh => $fh,
1874          line_no => 1,
1875             }, $class;
1876  }
1877  
1878  sub PRINT {
1879    my $self = shift;
1880    for (@_) {
1881      $self->{buffer} .= $_;
1882      while ($self->{buffer} =~ s/^([^\n]*\n)//) {
1883        my $line = $1;
1884        ++ $self->{line_no};
1885        $line =~ s|^\#line\s+---(?=\s)|#line $self->{line_no}|;
1886        print {$self->{fh}} $line;
1887      }
1888    }
1889  }
1890  
1891  sub PRINTF {
1892    my $self = shift;
1893    my $fmt = shift;
1894    $self->PRINT(sprintf($fmt, @_));
1895  }
1896  
1897  sub DESTROY {
1898    # Not necessary if we're careful to end with a "\n"
1899    my $self = shift;
1900    print {$self->{fh}} $self->{buffer};
1901  }
1902  
1903  sub UNTIE {
1904    # This sub does nothing, but is neccessary for references to be released.
1905  }
1906  
1907  sub end_marker {
1908    return $SECTION_END_MARKER;
1909  }
1910  
1911  
1912  1;
1913  __END__
1914  
1915  =head1 NAME
1916  
1917  ExtUtils::ParseXS - converts Perl XS code into C code
1918  
1919  =head1 SYNOPSIS
1920  
1921    use ExtUtils::ParseXS qw(process_file);
1922    
1923    process_file( filename => 'foo.xs' );
1924  
1925    process_file( filename => 'foo.xs',
1926                  output => 'bar.c',
1927                  'C++' => 1,
1928                  typemap => 'path/to/typemap',
1929                  hiertype => 1,
1930                  except => 1,
1931                  prototypes => 1,
1932                  versioncheck => 1,
1933                  linenumbers => 1,
1934                  optimize => 1,
1935                  prototypes => 1,
1936                );
1937  =head1 DESCRIPTION
1938  
1939  C<ExtUtils::ParseXS> will compile XS code into C code by embedding the constructs
1940  necessary to let C functions manipulate Perl values and creates the glue
1941  necessary to let Perl access those functions.  The compiler uses typemaps to
1942  determine how to map C function parameters and variables to Perl values.
1943  
1944  The compiler will search for typemap files called I<typemap>.  It will use
1945  the following search path to find default typemaps, with the rightmost
1946  typemap taking precedence.
1947  
1948      ../../../typemap:../../typemap:../typemap:typemap
1949  
1950  =head1 EXPORT
1951  
1952  None by default.  C<process_file()> may be exported upon request.
1953  
1954  
1955  =head1 FUNCTIONS
1956  
1957  =over 4
1958  
1959  =item process_xs()
1960  
1961  This function processes an XS file and sends output to a C file.
1962  Named parameters control how the processing is done.  The following
1963  parameters are accepted:
1964  
1965  =over 4
1966  
1967  =item B<C++>
1968  
1969  Adds C<extern "C"> to the C code.  Default is false.
1970  
1971  =item B<hiertype>
1972  
1973  Retains C<::> in type names so that C++ hierachical types can be
1974  mapped.  Default is false.
1975  
1976  =item B<except>
1977  
1978  Adds exception handling stubs to the C code.  Default is false.
1979  
1980  =item B<typemap>
1981  
1982  Indicates that a user-supplied typemap should take precedence over the
1983  default typemaps.  A single typemap may be specified as a string, or
1984  multiple typemaps can be specified in an array reference, with the
1985  last typemap having the highest precedence.
1986  
1987  =item B<prototypes>
1988  
1989  Generates prototype code for all xsubs.  Default is false.
1990  
1991  =item B<versioncheck>
1992  
1993  Makes sure at run time that the object file (derived from the C<.xs>
1994  file) and the C<.pm> files have the same version number.  Default is
1995  true.
1996  
1997  =item B<linenumbers>
1998  
1999  Adds C<#line> directives to the C output so error messages will look
2000  like they came from the original XS file.  Default is true.
2001  
2002  =item B<optimize>
2003  
2004  Enables certain optimizations.  The only optimization that is currently
2005  affected is the use of I<target>s by the output C code (see L<perlguts>).
2006  Not optimizing may significantly slow down the generated code, but this is the way
2007  B<xsubpp> of 5.005 and earlier operated.  Default is to optimize.
2008  
2009  =item B<inout>
2010  
2011  Enable recognition of C<IN>, C<OUT_LIST> and C<INOUT_LIST>
2012  declarations.  Default is true.
2013  
2014  =item B<argtypes>
2015  
2016  Enable recognition of ANSI-like descriptions of function signature.
2017  Default is true.
2018  
2019  =item B<s>
2020  
2021  I have no clue what this does.  Strips function prefixes?
2022  
2023  =back
2024  
2025  =item errors()
2026  
2027  This function returns the number of [a certain kind of] errors
2028  encountered during processing of the XS file.
2029  
2030  =back
2031  
2032  =head1 AUTHOR
2033  
2034  Based on xsubpp code, written by Larry Wall.
2035  
2036  Maintained by Ken Williams, <ken@mathforum.org>
2037  
2038  =head1 COPYRIGHT
2039  
2040  Copyright 2002-2003 Ken Williams.  All rights reserved.
2041  
2042  This library is free software; you can redistribute it and/or
2043  modify it under the same terms as Perl itself.
2044  
2045  Based on the ExtUtils::xsubpp code by Larry Wall and the Perl 5
2046  Porters, which was released under the same license terms.
2047  
2048  =head1 SEE ALSO
2049  
2050  L<perl>, ExtUtils::xsubpp, ExtUtils::MakeMaker, L<perlxs>, L<perlxstut>.
2051  
2052  =cut


Generated: Tue Mar 17 22:47:18 2015 Cross-referenced by PHPXref 0.7.1