This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Re: INC handlers and shutdown-time warnings
[perl5.git] / ext / B / B.xs
index f9c8647..4370c3e 100644 (file)
@@ -21,6 +21,9 @@ typedef FILE * InputStream;
 
 static const char* const svclassnames[] = {
     "B::NULL",
+#if PERL_VERSION >= 9
+    "B::BIND",
+#endif
     "B::IV",
     "B::NV",
     "B::RV",
@@ -28,7 +31,9 @@ static const char* const svclassnames[] = {
     "B::PVIV",
     "B::PVNV",
     "B::PVMG",
+#if PERL_VERSION <= 8
     "B::BM",
+#endif
 #if PERL_VERSION >= 9
     "B::GV",
 #endif
@@ -112,9 +117,20 @@ cc_opclass(pTHX_ const OP *o)
     if (o->op_type == OP_SASSIGN)
        return ((o->op_private & OPpASSIGN_BACKWARDS) ? OPc_UNOP : OPc_BINOP);
 
+    if (o->op_type == OP_AELEMFAST) {
+       if (o->op_flags & OPf_SPECIAL)
+           return OPc_BASEOP;
+       else
+#ifdef USE_ITHREADS
+           return OPc_PADOP;
+#else
+           return OPc_SVOP;
+#endif
+    }
+    
 #ifdef USE_ITHREADS
     if (o->op_type == OP_GV || o->op_type == OP_GVSV ||
-       o->op_type == OP_AELEMFAST || o->op_type == OP_RCATLINE)
+       o->op_type == OP_RCATLINE)
        return OPc_PADOP;
 #endif
 
@@ -235,6 +251,71 @@ make_sv_object(pTHX_ SV *arg, SV *sv)
     return arg;
 }
 
+#if PERL_VERSION >= 9
+static SV *
+make_temp_object(pTHX_ SV *arg, SV *temp)
+{
+    SV *target;
+    const char *const type = svclassnames[SvTYPE(temp)];
+    const IV iv = PTR2IV(temp);
+
+    target = newSVrv(arg, type);
+    sv_setiv(target, iv);
+
+    /* Need to keep our "temp" around as long as the target exists.
+       Simplest way seems to be to hang it from magic, and let that clear
+       it up.  No vtable, so won't actually get in the way of anything.  */
+    sv_magicext(target, temp, PERL_MAGIC_sv, NULL, NULL, 0);
+    /* magic object has had its reference count increased, so we must drop
+       our reference.  */
+    SvREFCNT_dec(temp);
+    return arg;
+}
+
+static SV *
+make_warnings_object(pTHX_ SV *arg, STRLEN *warnings)
+{
+    const char *type = 0;
+    dMY_CXT;
+    IV iv = sizeof(specialsv_list)/sizeof(SV*);
+
+    /* Counting down is deliberate. Before the split between make_sv_object
+       and make_warnings_obj there appeared to be a bug - Nullsv and pWARN_STD
+       were both 0, so you could never get a B::SPECIAL for pWARN_STD  */
+
+    while (iv--) {
+       if ((SV*)warnings == specialsv_list[iv]) {
+           type = "B::SPECIAL";
+           break;
+       }
+    }
+    if (type) {
+       sv_setiv(newSVrv(arg, type), iv);
+       return arg;
+    } else {
+       /* B assumes that warnings are a regular SV. Seems easier to keep it
+          happy by making them into a regular SV.  */
+       return make_temp_object(aTHX_ arg,
+                               newSVpvn((char *)(warnings + 1), *warnings));
+    }
+}
+
+static SV *
+make_cop_io_object(pTHX_ SV *arg, COP *cop)
+{
+    SV *const value = newSV(0);
+
+    Perl_emulate_cop_io(aTHX_ cop, value);
+
+    if(SvOK(value)) {
+       return make_temp_object(aTHX_ arg, newSVsv(value));
+    } else {
+       SvREFCNT_dec(value);
+       return make_sv_object(aTHX_ arg, NULL);
+    }
+}
+#endif
+
 static SV *
 make_mg_object(pTHX_ SV *arg, MAGIC *mg)
 {
@@ -406,7 +487,12 @@ walkoptree(pTHX_ SV *opsv, const char *method)
        }
     }
     if (o && (cc_opclass(aTHX_ o) == OPc_PMOP) && o->op_type != OP_PUSHRE
-           && (kid = cPMOPo->op_pmreplroot))
+#if PERL_VERSION >= 9
+           && (kid = cPMOPo->op_pmreplrootu.op_pmreplroot)
+#else
+           && (kid = cPMOPo->op_pmreplroot)
+#endif
+       )
     {
        sv_setiv(newSVrv(opsv, cc_opclassname(aTHX_ kid)), PTR2IV(kid));
        walkoptree(aTHX_ opsv, method);
@@ -432,7 +518,11 @@ oplist(pTHX_ OP *o, SV **SP)
        XPUSHs(opsv);
         switch (o->op_type) {
        case OP_SUBST:
+#if PERL_VERSION >= 9
+            SP = oplist(aTHX_ cPMOPo->op_pmstashstartu.op_pmreplstart, SP);
+#else
             SP = oplist(aTHX_ cPMOPo->op_pmreplstart, SP);
+#endif
             continue;
        case OP_SORT:
            if (o->op_flags & OPf_STACKED && o->op_flags & OPf_SPECIAL) {
@@ -485,6 +575,10 @@ typedef GV *B__GV;
 typedef IO     *B__IO;
 
 typedef MAGIC  *B__MAGIC;
+typedef HE      *B__HE;
+#if PERL_VERSION >= 9
+typedef struct refcounted_he   *B__RHE;
+#endif
 
 MODULE = B     PACKAGE = B     PREFIX = B_
 
@@ -492,18 +586,18 @@ PROTOTYPES: DISABLE
 
 BOOT:
 {
-    HV *stash = gv_stashpvn("B", 1, TRUE);
+    HV *stash = gv_stashpvn("B", 1, GV_ADD);
     AV *export_ok = perl_get_av("B::EXPORT_OK",TRUE);
     MY_CXT_INIT;
     specialsv_list[0] = Nullsv;
     specialsv_list[1] = &PL_sv_undef;
     specialsv_list[2] = &PL_sv_yes;
     specialsv_list[3] = &PL_sv_no;
-    specialsv_list[4] = pWARN_ALL;
-    specialsv_list[5] = pWARN_NONE;
-    specialsv_list[6] = pWARN_STD;
+    specialsv_list[4] = (SV *) pWARN_ALL;
+    specialsv_list[5] = (SV *) pWARN_NONE;
+    specialsv_list[6] = (SV *) pWARN_STD;
 #if PERL_VERSION <= 8
-#  define CVf_ASSERTION        0
+#  define OPpPAD_STATE 0
 #endif
 #include "defsubs.h"
 }
@@ -512,11 +606,17 @@ BOOT:
 #define B_init_av()    PL_initav
 #define B_inc_gv()     PL_incgv
 #define B_check_av()   PL_checkav_save
+#if PERL_VERSION > 8
+#  define B_unitcheck_av()     PL_unitcheckav_save
+#else
+#  define B_unitcheck_av()     NULL
+#endif
 #define B_begin_av()   PL_beginav_save
 #define B_end_av()     PL_endav
 #define B_main_root()  PL_main_root
 #define B_main_start() PL_main_start
 #define B_amagic_generation()  PL_amagic_generation
+#define B_sub_generation()     PL_sub_generation
 #define B_defstash()   PL_defstash
 #define B_curstash()   PL_curstash
 #define B_dowarn()     PL_dowarn
@@ -535,6 +635,13 @@ B_init_av()
 B::AV
 B_check_av()
 
+#if PERL_VERSION >= 9
+
+B::AV
+B_unitcheck_av()
+
+#endif
+
 B::AV
 B_begin_av()
 
@@ -563,6 +670,9 @@ B_main_start()
 long 
 B_amagic_generation()
 
+long
+B_sub_generation()
+
 B::AV
 B_comppadlist()
 
@@ -735,7 +845,6 @@ threadsv_names()
 #define OP_type(o)     o->op_type
 #if PERL_VERSION >= 9
 #  define OP_opt(o)    o->op_opt
-#  define OP_static(o) o->op_static
 #else
 #  define OP_seq(o)    o->op_seq
 #endif
@@ -802,10 +911,6 @@ U8
 OP_opt(o)
        B::OP           o
 
-U8
-OP_static(o)
-       B::OP           o
-
 #else
 
 U16
@@ -875,22 +980,27 @@ LISTOP_children(o)
     OUTPUT:
         RETVAL
 
-#define PMOP_pmreplroot(o)     o->op_pmreplroot
-#define PMOP_pmreplstart(o)    o->op_pmreplstart
+#if PERL_VERSION >= 9
+#  define PMOP_pmreplstart(o)  o->op_pmstashstartu.op_pmreplstart
+#else
+#  define PMOP_pmreplstart(o)  o->op_pmreplstart
+#  define PMOP_pmpermflags(o)  o->op_pmpermflags
+#  define PMOP_pmdynflags(o)      o->op_pmdynflags
+#endif
 #define PMOP_pmnext(o)         o->op_pmnext
 #define PMOP_pmregexp(o)       PM_GETRE(o)
 #ifdef USE_ITHREADS
 #define PMOP_pmoffset(o)       o->op_pmoffset
-#define PMOP_pmstashpv(o)      o->op_pmstashpv
+#define PMOP_pmstashpv(o)      PmopSTASHPV(o);
 #else
-#define PMOP_pmstash(o)                o->op_pmstash
+#define PMOP_pmstash(o)                PmopSTASH(o);
 #endif
 #define PMOP_pmflags(o)                o->op_pmflags
-#define PMOP_pmpermflags(o)    o->op_pmpermflags
-#define PMOP_pmdynflags(o)      o->op_pmdynflags
 
 MODULE = B     PACKAGE = B::PMOP               PREFIX = PMOP_
 
+#if PERL_VERSION <= 8
+
 void
 PMOP_pmreplroot(o)
        B::PMOP         o
@@ -900,26 +1010,55 @@ PMOP_pmreplroot(o)
        root = o->op_pmreplroot;
        /* OP_PUSHRE stores an SV* instead of an OP* in op_pmreplroot */
        if (o->op_type == OP_PUSHRE) {
-#ifdef USE_ITHREADS
+#  ifdef USE_ITHREADS
             sv_setiv(ST(0), INT2PTR(PADOFFSET,root) );
-#else
+#  else
            sv_setiv(newSVrv(ST(0), root ?
                             svclassnames[SvTYPE((SV*)root)] : "B::SV"),
                     PTR2IV(root));
-#endif
+#  endif
        }
        else {
            sv_setiv(newSVrv(ST(0), cc_opclassname(aTHX_ root)), PTR2IV(root));
        }
 
+#else
+
+void
+PMOP_pmreplroot(o)
+       B::PMOP         o
+    CODE:
+       ST(0) = sv_newmortal();
+       if (o->op_type == OP_PUSHRE) {
+#  ifdef USE_ITHREADS
+            sv_setiv(ST(0), o->op_pmreplrootu.op_pmtargetoff);
+#  else
+           GV *const target = o->op_pmreplrootu.op_pmtargetgv;
+           sv_setiv(newSVrv(ST(0), target ?
+                            svclassnames[SvTYPE((SV*)target)] : "B::SV"),
+                    PTR2IV(target));
+#  endif
+       }
+       else {
+           OP *const root = o->op_pmreplrootu.op_pmreplroot; 
+           sv_setiv(newSVrv(ST(0), cc_opclassname(aTHX_ root)),
+                    PTR2IV(root));
+       }
+
+#endif
+
 B::OP
 PMOP_pmreplstart(o)
        B::PMOP         o
 
+#if PERL_VERSION < 9
+
 B::PMOP
 PMOP_pmnext(o)
        B::PMOP         o
 
+#endif
+
 #ifdef USE_ITHREADS
 
 IV
@@ -942,6 +1081,8 @@ U32
 PMOP_pmflags(o)
        B::PMOP         o
 
+#if PERL_VERSION < 9
+
 U32
 PMOP_pmpermflags(o)
        B::PMOP         o
@@ -950,6 +1091,8 @@ U8
 PMOP_pmdynflags(o)
         B::PMOP         o
 
+#endif
+
 void
 PMOP_precomp(o)
        B::PMOP         o
@@ -960,6 +1103,20 @@ PMOP_precomp(o)
        if (rx)
            sv_setpvn(ST(0), rx->precomp, rx->prelen);
 
+#if PERL_VERSION >= 9
+
+void
+PMOP_reflags(o)
+       B::PMOP         o
+       REGEXP *        rx = NO_INIT
+    CODE:
+       ST(0) = sv_newmortal();
+       rx = PM_GETRE(o);
+       if (rx)
+           sv_setuv(ST(0), rx->extflags);
+
+#endif
+
 #define SVOP_sv(o)     cSVOPo->op_sv
 #define SVOP_gv(o)     ((GV*)cSVOPo->op_sv)
 
@@ -1042,10 +1199,13 @@ LOOP_lastop(o)
 #define COP_file(o)    CopFILE(o)
 #define COP_filegv(o)  CopFILEGV(o)
 #define COP_cop_seq(o) o->cop_seq
-#define COP_arybase(o) o->cop_arybase
+#define COP_arybase(o) CopARYBASE_get(o)
 #define COP_line(o)    CopLINE(o)
-#define COP_warnings(o)        o->cop_warnings
-#define COP_io(o)      o->cop_io
+#define COP_hints(o)   CopHINTS_get(o)
+#if PERL_VERSION < 9
+#  define COP_warnings(o)  o->cop_warnings
+#  define COP_io(o)    o->cop_io
+#endif
 
 MODULE = B     PACKAGE = B::COP                PREFIX = COP_
 
@@ -1082,6 +1242,32 @@ U32
 COP_line(o)
        B::COP  o
 
+#if PERL_VERSION >= 9
+
+void
+COP_warnings(o)
+       B::COP  o
+       PPCODE:
+       ST(0) = make_warnings_object(aTHX_ sv_newmortal(), o->cop_warnings);
+       XSRETURN(1);
+
+void
+COP_io(o)
+       B::COP  o
+       PPCODE:
+       ST(0) = make_cop_io_object(aTHX_ sv_newmortal(), o);
+       XSRETURN(1);
+
+B::RHE
+COP_hints_hash(o)
+       B::COP o
+    CODE:
+       RETVAL = o->cop_hints_hash;
+    OUTPUT:
+       RETVAL
+
+#else
+
 B::SV
 COP_warnings(o)
        B::COP  o
@@ -1090,6 +1276,12 @@ B::SV
 COP_io(o)
        B::COP  o
 
+#endif
+
+U32
+COP_hints(o)
+       B::COP  o
+
 MODULE = B     PACKAGE = B::SV
 
 U32
@@ -1184,6 +1376,22 @@ NV
 SvNVX(sv)
        B::NV   sv
 
+U32
+COP_SEQ_RANGE_LOW(sv)
+       B::NV   sv
+
+U32
+COP_SEQ_RANGE_HIGH(sv)
+       B::NV   sv
+
+U32
+PARENT_PAD_INDEX(sv)
+       B::NV   sv
+
+U32
+PARENT_FAKELEX_FLAGS(sv)
+       B::NV   sv
+
 MODULE = B     PACKAGE = B::RV         PREFIX = Sv
 
 B::SV
@@ -1232,13 +1440,16 @@ SvPV(sv)
             sv_setpvn(ST(0), NULL, 0);
         }
 
+# This used to read 257. I think that that was buggy - should have been 258.
+# (The "\0", the flags byte, and 256 for the table.  Not that anything
+# anywhere calls this method.  NWC.
 void
 SvPVBM(sv)
        B::PV   sv
     CODE:
         ST(0) = sv_newmortal();
        sv_setpvn(ST(0), SvPVX_const(sv),
-           SvCUR(sv) + (SvTYPE(sv) == SVt_PVBM ? 257 : 0));
+           SvCUR(sv) + (SvVALID(sv) ? 256 + PERL_FBM_TABLE_OFFSET : 0));
 
 
 STRLEN
@@ -1308,7 +1519,7 @@ IV
 MgREGEX(mg)
        B::MAGIC        mg
     CODE:
-        if( mg->mg_type == 'r' ) {
+        if(mg->mg_type == PERL_MAGIC_qr) {
             RETVAL = MgREGEX(mg);
         }
         else {
@@ -1321,8 +1532,9 @@ SV*
 precomp(mg)
         B::MAGIC        mg
     CODE:
-        if (mg->mg_type == 'r') {
+        if (mg->mg_type == PERL_MAGIC_qr) {
             REGEXP* rx = (REGEXP*)mg->mg_obj;
+            RETVAL = Nullsv;
             if( rx )
                 RETVAL = newSVpvn( rx->precomp, rx->prelen );
         }
@@ -1374,7 +1586,7 @@ I32
 BmUSEFUL(sv)
        B::BM   sv
 
-U16
+U32
 BmPREVIOUS(sv)
        B::BM   sv
 
@@ -1390,7 +1602,7 @@ BmTABLE(sv)
     CODE:
        str = SvPV(sv, len);
        /* Boyer-Moore table is just after string and its safety-margin \0 */
-       ST(0) = sv_2mortal(newSVpvn(str + len + 1, 256));
+       ST(0) = sv_2mortal(newSVpvn(str + len + PERL_FBM_TABLE_OFFSET, 256));
 
 MODULE = B     PACKAGE = B::GV         PREFIX = Gv
 
@@ -1563,6 +1775,17 @@ SSize_t
 AvMAX(av)
        B::AV   av
 
+#if PERL_VERSION < 9
+                          
+
+#define AvOFF(av) ((XPVAV*)SvANY(av))->xof_off
+
+IV
+AvOFF(av)
+       B::AV   av
+
+#endif
+
 void
 AvARRAY(av)
        B::AV   av
@@ -1584,6 +1807,16 @@ AvARRAYelt(av, idx)
        else
            XPUSHs(make_sv_object(aTHX_ sv_newmortal(), NULL));
 
+#if PERL_VERSION < 9
+                                  
+MODULE = B     PACKAGE = B::AV
+
+U8
+AvFLAGS(av)
+       B::AV   av
+
+#endif
+
 MODULE = B     PACKAGE = B::FM         PREFIX = Fm
 
 IV
@@ -1603,10 +1836,18 @@ CvSTASH(cv)
 B::OP
 CvSTART(cv)
        B::CV   cv
+    CODE:
+       RETVAL = CvISXSUB(cv) ? NULL : CvSTART(cv);
+    OUTPUT:
+       RETVAL
 
 B::OP
 CvROOT(cv)
        B::CV   cv
+    CODE:
+       RETVAL = CvISXSUB(cv) ? NULL : CvROOT(cv);
+    OUTPUT:
+       RETVAL
 
 B::GV
 CvGV(cv)
@@ -1636,7 +1877,7 @@ void
 CvXSUB(cv)
        B::CV   cv
     CODE:
-       ST(0) = sv_2mortal(newSViv(PTR2IV(CvXSUB(cv))));
+       ST(0) = sv_2mortal(newSViv(CvISXSUB(cv) ? PTR2IV(CvXSUB(cv)) : 0));
 
 
 void
@@ -1645,7 +1886,7 @@ CvXSUBANY(cv)
     CODE:
        ST(0) = CvCONST(cv) ?
            make_sv_object(aTHX_ sv_newmortal(),(SV *)CvXSUBANY(cv).any_ptr) :
-           sv_2mortal(newSViv(CvXSUBANY(cv).any_iv));
+           sv_2mortal(newSViv(CvISXSUB(cv) ? CvXSUBANY(cv).any_iv : 0));
 
 MODULE = B    PACKAGE = B::CV
 
@@ -1682,6 +1923,14 @@ char *
 HvNAME(hv)
        B::HV   hv
 
+#if PERL_VERSION < 9
+
+B::PMOP
+HvPMROOT(hv)
+       B::HV   hv
+
+#endif
+
 void
 HvARRAY(hv)
        B::HV   hv
@@ -1697,3 +1946,31 @@ HvARRAY(hv)
                PUSHs(make_sv_object(aTHX_ sv_newmortal(), sv));
            }
        }
+
+MODULE = B     PACKAGE = B::HE         PREFIX = He
+
+B::SV
+HeVAL(he)
+       B::HE he
+
+U32
+HeHASH(he)
+       B::HE he
+
+B::SV
+HeSVKEY_force(he)
+       B::HE he
+
+MODULE = B     PACKAGE = B::RHE        PREFIX = RHE_
+
+#if PERL_VERSION >= 9
+
+SV*
+RHE_HASH(h)
+       B::RHE h
+    CODE:
+       RETVAL = newRV( (SV*)Perl_refcounted_he_chain_2hv(aTHX_ h) );
+    OUTPUT:
+       RETVAL
+
+#endif