add newer malloc.c from Ilya Zakharevich <ilya@math.ohio-state.edu>
[p5sagit/p5-mst-13.2.git] / lib / ExtUtils / xsubpp
index ac1378d..8e253ff 100755 (executable)
@@ -6,7 +6,7 @@ xsubpp - compiler to convert Perl XS code into C code
 
 =head1 SYNOPSIS
 
-B<xsubpp> [B<-v>] [B<-C++>] [B<-except>] [B<-s pattern>] [B<-prototypes>] [B<-noversioncheck>] [B<-nolinenumbers>] [B<-typemap typemap>]... file.xs
+B<xsubpp> [B<-v>] [B<-C++>] [B<-except>] [B<-s pattern>] [B<-prototypes>] [B<-noversioncheck>] [B<-nolinenumbers>] [B<-typemap typemap>] [B<-object_capi>]... file.xs
 
 =head1 DESCRIPTION
 
@@ -59,7 +59,11 @@ number.
 
 Prevents the inclusion of `#line' directives in the output.
 
-=back
+=item B<-object_capi>
+
+Compile code as C in a PERL_OBJECT environment.
+
+back
 
 =head1 ENVIRONMENT
 
@@ -83,11 +87,13 @@ require 5.002;
 use Cwd;
 use vars '$cplusplus';
 
+use Config;
+
 sub Q ;
 
 # Global Constants
 
-$XSUBPP_version = "1.9504";
+$XSUBPP_version = "1.9506";
 
 my ($Is_VMS, $SymSet);
 if ($^O eq 'VMS') {
@@ -103,6 +109,8 @@ $FH = 'File0000' ;
 $usage = "Usage: xsubpp [-v] [-C++] [-except] [-prototypes] [-noversioncheck] [-nolinenumbers] [-s pattern] [-typemap typemap]... file.xs\n";
 
 $proto_re = "[" . quotemeta('\$%&*@;') . "]" ;
+# mjn
+$OBJ   = 1 if $Config{'ccflags'} =~ /PERL_OBJECT/i;
 
 $except = "";
 $WantPrototypes = -1 ;
@@ -118,6 +126,7 @@ SWITCH: while (@ARGV and $ARGV[0] =~ /^-./) {
     $WantPrototypes = 1, next SWITCH   if $flag eq 'prototypes';
     $WantVersionChk = 0, next SWITCH   if $flag eq 'noversioncheck';
     $WantVersionChk = 1, next SWITCH   if $flag eq 'versioncheck';
+    $WantCAPI = 1, next SWITCH    if $flag eq 'object_capi';
     $except = " TRY",  next SWITCH     if $flag eq 'except';
     push(@tm,shift),   next SWITCH     if $flag eq 'typemap';
     $WantLineNumbers = 0, next SWITCH  if $flag eq 'nolinenumbers';
@@ -294,7 +303,7 @@ sub print_section {
     do { $_ = shift(@line) } while !/\S/ && @line;
     
     print("#line ", $line_no[@line_no - @line -1], " \"$filename\"\n")
-       if $WantLineNumbers && !/^\s*#\s*line\b/;
+       if $WantLineNumbers && !/^\s*#\s*line\b/ && !/^#if XSubPPtmp/;
     for (;  defined($_) && !/^$BLOCK_re/o;  $_ = shift(@line)) {
        print "$_\n";
     }
@@ -371,6 +380,10 @@ sub INPUT_handler {
 sub OUTPUT_handler {
     for (;  !/^$BLOCK_re/o;  $_ = shift(@line)) {
        next unless /\S/;
+       if (/^\s*SETMAGIC\s*:\s*(ENABLE|DISABLE)\s*/) {
+           $DoSetMagic = ($1 eq "ENABLE" ? 1 : 0);
+           next;
+       }
        my ($outarg, $outcode) = /^\s*(\S+)\s*(.*?)\s*$/s ;
        blurt ("Error: duplicate OUTPUT argument '$outarg' ignored"), next
            if $outargs{$outarg} ++ ;
@@ -384,11 +397,12 @@ sub OUTPUT_handler {
            unless defined($args_match{$outarg});
        blurt("Error: No input definition for OUTPUT argument '$outarg' - ignored"), next
            unless defined $var_types{$outarg} ;
+       $var_num = $args_match{$outarg};
        if ($outcode) {
            print "\t$outcode\n";
+           print "\tSvSETMAGIC(ST(" , $var_num-1 , "));\n" if $DoSetMagic;
        } else {
-           $var_num = $args_match{$outarg};
-           &generate_output($var_types{$outarg}, $var_num, $outarg); 
+           &generate_output($var_types{$outarg}, $var_num, $outarg, $DoSetMagic);
        }
     }
 }
@@ -709,6 +723,10 @@ print("#line 1 \"$filename\"\n")
 while (<$FH>) {
     last if ($Module, $Package, $Prefix) =
        /^MODULE\s*=\s*([\w:]+)(?:\s+PACKAGE\s*=\s*([\w:]+))?(?:\s+PREFIX\s*=\s*(\S+))?\s*$/;
+
+    if ($OBJ) {
+        s/#if(?:def|\s+defined)\s+(\(__cplusplus\)|__cplusplus)/#if defined(__cplusplus) && !defined(PERL_OBJECT)/;
+    }
     print $_;
 }
 &Exit unless defined $_;
@@ -875,6 +893,7 @@ while (fetch_para()) {
     }
     $XSStack[$XSS_work_idx]{functions}{$Full_func_name} ++ ;
     %XsubAliases = %XsubAliasValues = ();
+    $DoSetMagic = 1;
 
     @args = split(/\s*,\s*/, $orig_args);
     if (defined($class)) {
@@ -1059,7 +1078,8 @@ EOF
        if ($gotRETVAL && $RETVAL_code) {
            print "\t$RETVAL_code\n";
        } elsif ($gotRETVAL || $wantRETVAL) {
-           &generate_output($ret_type, 0, 'RETVAL');
+           # RETVAL almost never needs SvSETMAGIC()
+           &generate_output($ret_type, 0, 'RETVAL', 0);
        }
 
        # do cleanup
@@ -1160,6 +1180,19 @@ EOF
 }
 
 # print initialization routine
+if ($WantCAPI) {
+print Q<<"EOF";
+#
+##ifdef __cplusplus
+#extern "C"
+##endif
+#XS(boot__CAPI_entry)
+#[[
+#    dXSARGS;
+#    char* file = __FILE__;
+#
+EOF
+} else {
 print Q<<"EOF";
 ##ifdef __cplusplus
 #extern "C"
@@ -1170,6 +1203,7 @@ print Q<<"EOF";
 #    char* file = __FILE__;
 #
 EOF
+}
 
 print Q<<"EOF" if $WantVersionChk ;
 #    XS_VERSION_BOOTCHECK ;
@@ -1200,7 +1234,25 @@ print Q<<"EOF";;
 #    ST(0) = &sv_yes;
 #    XSRETURN(1);
 #]]
+#
+EOF
+
+if ($WantCAPI) { 
+print Q<<"EOF";
+#
+##define XSCAPI(name) void name(CV* cv, void* pPerl)
+#
+##ifdef __cplusplus
+#extern "C"
+##endif
+#XSCAPI(boot_$Module_cname)
+#[[
+#    SetCPerlObj(pPerl);
+#    boot__CAPI_entry(cv);
+#]]
+#
 EOF
+}
 
 warn("Please specify prototyping behavior for $filename (see perlxs manual)\n") 
     unless $ProtoUsed ;
@@ -1283,7 +1335,7 @@ sub generate_init {
 }
 
 sub generate_output {
-    local($type, $num, $var) = @_;
+    local($type, $num, $var, $do_setmagic) = @_;
     local($arg) = "ST(" . ($num - ($num != 0)) . ")";
     local($argoff) = $num - 1;
     local($ntype);
@@ -1291,6 +1343,7 @@ sub generate_output {
     $type = TidyType($type) ;
     if ($type =~ /^array\(([^,]*),(.*)\)/) {
            print "\tsv_setpvn($arg, (char *)$var, $2 * sizeof($1)), XFree((char *)$var);\n";
+           print "\tSvSETMAGIC($arg);\n" if $do_setmagic;
     } else {
            blurt("Error: '$type' not in typemap"), return
                unless defined($type_kind{$type});
@@ -1312,6 +1365,7 @@ sub generate_output {
                $subexpr =~ s/\n\t/\n\t\t/g;
                $expr =~ s/DO_ARRAY_ELEM\n/$subexpr/;
                eval "print qq\a$expr\a";
+               print "\t\tSvSETMAGIC(ST(ix_$var));\n" if $do_setmagic;
            }
            elsif ($var eq 'RETVAL') {
                if ($expr =~ /^\t\$arg = new/) {
@@ -1319,6 +1373,7 @@ sub generate_output {
                    # mortalize it.
                    eval "print qq\a$expr\a";
                    print "\tsv_2mortal(ST(0));\n";
+                   print "\tSvSETMAGIC(ST(0));\n" if $do_setmagic;
                }
                elsif ($expr =~ /^\s*\$arg\s*=/) {
                    # We expect that $arg has refcnt >=1, so we need
@@ -1329,6 +1384,7 @@ sub generate_output {
                    # ignored by REFCNT_dec. Builtin values have REFCNT==0.
                    eval "print qq\a$expr\a";
                    print "\tif (SvREFCNT(ST(0))) sv_2mortal(ST(0));\n";
+                   print "\tSvSETMAGIC(ST(0));\n" if $do_setmagic;
                }
                else {
                    # Just hope that the entry would safely write it
@@ -1337,10 +1393,12 @@ sub generate_output {
                    # works too.
                    print "\tST(0) = sv_newmortal();\n";
                    eval "print qq\a$expr\a";
+                   # new mortals don't have set magic
                }
            }
            elsif ($arg =~ /^ST\(\d+\)$/) {
                eval "print qq\a$expr\a";
+               print "\tSvSETMAGIC($arg);\n" if $do_setmagic;
            }
     }
 }