*/
#define PERL_NO_GET_CONTEXT
+#define PERL_EXT
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
"B::NULL",
"B::IV",
"B::NV",
-#if PERL_VERSION <= 10
- "B::RV",
-#endif
"B::PV",
"B::INVLIST",
"B::PVIV",
"B::PVNV",
"B::PVMG",
-#if PERL_VERSION >= 11
"B::REGEXP",
-#endif
"B::GV",
"B::PVLV",
"B::AV",
OPc_PADOP, /* 8 */
OPc_PVOP, /* 9 */
OPc_LOOP, /* 10 */
- OPc_COP /* 11 */
+ OPc_COP, /* 11 */
+ OPc_METHOP, /* 12 */
+ OPc_UNOP_AUX /* 13 */
} opclass;
static const char* const opclassnames[] = {
"B::PADOP",
"B::PVOP",
"B::LOOP",
- "B::COP"
+ "B::COP",
+ "B::METHOP",
+ "B::UNOP_AUX"
};
static const size_t opsizes[] = {
sizeof(PADOP),
sizeof(PVOP),
sizeof(LOOP),
- sizeof(COP)
+ sizeof(COP),
+ sizeof(METHOP),
+ sizeof(UNOP_AUX),
};
#define MY_CXT_KEY "B::_guts" XS_VERSION
typedef struct {
- int x_walkoptree_debug; /* Flag for walkoptree debug hook */
SV * x_specialsv_list[7];
+ int x_walkoptree_debug; /* Flag for walkoptree debug hook */
} my_cxt_t;
START_MY_CXT
#define walkoptree_debug (MY_CXT.x_walkoptree_debug)
#define specialsv_list (MY_CXT.x_specialsv_list)
+
+static void B_init_my_cxt(pTHX_ my_cxt_t * cxt) {
+ cxt->x_specialsv_list[0] = Nullsv;
+ cxt->x_specialsv_list[1] = &PL_sv_undef;
+ cxt->x_specialsv_list[2] = &PL_sv_yes;
+ cxt->x_specialsv_list[3] = &PL_sv_no;
+ cxt->x_specialsv_list[4] = (SV *) pWARN_ALL;
+ cxt->x_specialsv_list[5] = (SV *) pWARN_NONE;
+ cxt->x_specialsv_list[6] = (SV *) pWARN_STD;
+}
+
static opclass
cc_opclass(pTHX_ const OP *o)
{
if (!o)
return OPc_NULL;
- if (o->op_type == 0)
+ if (o->op_type == 0) {
+ if (o->op_targ == OP_NEXTSTATE || o->op_targ == OP_DBSTATE)
+ return OPc_COP;
return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;
+ }
if (o->op_type == OP_SASSIGN)
return ((o->op_private & OPpASSIGN_BACKWARDS) ? OPc_UNOP : OPc_BINOP);
if (o->op_type == OP_AELEMFAST) {
-#if PERL_VERSION <= 14
- if (o->op_flags & OPf_SPECIAL)
- return OPc_BASEOP;
- else
-#endif
#ifdef USE_ITHREADS
return OPc_PADOP;
#else
return OPc_BASEOP;
else
return OPc_PVOP;
+ case OA_METHOP:
+ return OPc_METHOP;
+ case OA_UNOP_AUX:
+ return OPc_UNOP_AUX;
}
warn("can't determine class of operator %s, assuming BASEOP\n",
OP_NAME(o));
PUTBACK;
perl_call_method(method, G_DISCARD);
if (o && (o->op_flags & OPf_KIDS)) {
- for (kid = ((UNOP*)o)->op_first; kid; kid = kid->op_sibling) {
+ for (kid = ((UNOP*)o)->op_first; kid; kid = OpSIBLING(kid)) {
ref = walkoptree(aTHX_ kid, method, ref);
}
}
continue;
case OP_SORT:
if (o->op_flags & OPf_STACKED && o->op_flags & OPf_SPECIAL) {
- OP *kid = cLISTOPo->op_first->op_sibling; /* pass pushmark */
+ OP *kid = OpSIBLING(cLISTOPo->op_first); /* pass pushmark */
kid = kUNOP->op_first; /* pass rv2gv */
kid = kUNOP->op_first; /* pass leave */
SP = oplist(aTHX_ kid->op_next, SP);
typedef PVOP *B__PVOP;
typedef LOOP *B__LOOP;
typedef COP *B__COP;
+typedef METHOP *B__METHOP;
typedef SV *B__SV;
typedef SV *B__IV;
typedef SV *B__PV;
typedef SV *B__NV;
typedef SV *B__PVMG;
-#if PERL_VERSION >= 11
typedef SV *B__REGEXP;
-#endif
typedef SV *B__PVLV;
typedef SV *B__BM;
typedef SV *B__RV;
#ifdef PadlistARRAY
typedef PADLIST *B__PADLIST;
#endif
+typedef PADNAMELIST *B__PADNAMELIST;
+typedef PADNAME *B__PADNAME;
+
#ifdef MULTIPLICITY
# define ASSIGN_COMMON_ALIAS(prefix, var) \
- STMT_START { XSANY.any_i32 = offsetof(struct interpreter, prefix##var); } STMT_END
+ STMT_START { XSANY.any_i32 = STRUCT_OFFSET(struct interpreter, prefix##var); } STMT_END
#else
# define ASSIGN_COMMON_ALIAS(prefix, var) \
STMT_START { XSANY.any_ptr = (void *)&PL_##var; } STMT_END
-#define SVp 0x00000
-#define U32p 0x10000
-#define line_tp 0x20000
-#define OPp 0x30000
-#define PADOFFSETp 0x40000
-#define U8p 0x50000
-#define IVp 0x60000
-#define char_pp 0x70000
+#define SVp 0x0
+#define U32p 0x1
+#define line_tp 0x2
+#define OPp 0x3
+#define PADOFFSETp 0x4
+#define U8p 0x5
+#define IVp 0x6
+#define char_pp 0x7
+/* Keep this last: */
+#define op_offset_special 0x8
/* table that drives most of the B::*OP methods */
-struct OP_methods {
+static const struct OP_methods {
const char *name;
- STRLEN namelen;
- I32 type;
- size_t offset; /* if -1, access is handled on a case-by-case basis */
+ U8 namelen;
+ U8 type; /* if op_offset_special, access is handled on a case-by-case basis */
+ U16 offset;
} op_methods[] = {
- STR_WITH_LEN("next"), OPp, offsetof(struct op, op_next), /* 0*/
- STR_WITH_LEN("sibling"), OPp, offsetof(struct op, op_sibling), /* 1*/
- STR_WITH_LEN("targ"), PADOFFSETp, offsetof(struct op, op_targ), /* 2*/
- STR_WITH_LEN("flags"), U8p, offsetof(struct op, op_flags), /* 3*/
- STR_WITH_LEN("private"), U8p, offsetof(struct op, op_private), /* 4*/
- STR_WITH_LEN("first"), OPp, offsetof(struct unop, op_first), /* 5*/
- STR_WITH_LEN("last"), OPp, offsetof(struct binop, op_last), /* 6*/
- STR_WITH_LEN("other"), OPp, offsetof(struct logop, op_other), /* 7*/
- STR_WITH_LEN("pmreplstart"), 0, -1, /* 8*/
- STR_WITH_LEN("redoop"), OPp, offsetof(struct loop, op_redoop), /* 9*/
- STR_WITH_LEN("nextop"), OPp, offsetof(struct loop, op_nextop), /*10*/
- STR_WITH_LEN("lastop"), OPp, offsetof(struct loop, op_lastop), /*11*/
- STR_WITH_LEN("pmflags"), U32p, offsetof(struct pmop, op_pmflags), /*12*/
-#if PERL_VERSION >= 17
- STR_WITH_LEN("code_list"),OPp, offsetof(struct pmop, op_code_list),/*13*/
+ { STR_WITH_LEN("next"), OPp, STRUCT_OFFSET(struct op, op_next), },/* 0*/
+ { STR_WITH_LEN("sibling"), op_offset_special, 0, },/* 1*/
+ { STR_WITH_LEN("targ"), PADOFFSETp, STRUCT_OFFSET(struct op, op_targ), },/* 2*/
+ { STR_WITH_LEN("flags"), U8p, STRUCT_OFFSET(struct op, op_flags), },/* 3*/
+ { STR_WITH_LEN("private"), U8p, STRUCT_OFFSET(struct op, op_private), },/* 4*/
+ { STR_WITH_LEN("first"), OPp, STRUCT_OFFSET(struct unop, op_first), },/* 5*/
+ { STR_WITH_LEN("last"), OPp, STRUCT_OFFSET(struct binop, op_last), },/* 6*/
+ { STR_WITH_LEN("other"), OPp, STRUCT_OFFSET(struct logop, op_other), },/* 7*/
+ { STR_WITH_LEN("pmreplstart"), op_offset_special, 0, },/* 8*/
+ { STR_WITH_LEN("redoop"), OPp, STRUCT_OFFSET(struct loop, op_redoop), },/* 9*/
+ { STR_WITH_LEN("nextop"), OPp, STRUCT_OFFSET(struct loop, op_nextop), },/*10*/
+ { STR_WITH_LEN("lastop"), OPp, STRUCT_OFFSET(struct loop, op_lastop), },/*11*/
+ { STR_WITH_LEN("pmflags"), U32p, STRUCT_OFFSET(struct pmop, op_pmflags),},/*12*/
+ { STR_WITH_LEN("code_list"),OPp, STRUCT_OFFSET(struct pmop, op_code_list),},/*13*/
+ { STR_WITH_LEN("sv"), SVp, STRUCT_OFFSET(struct svop, op_sv), },/*14*/
+ { STR_WITH_LEN("gv"), SVp, STRUCT_OFFSET(struct svop, op_sv), },/*15*/
+ { STR_WITH_LEN("padix"), PADOFFSETp,STRUCT_OFFSET(struct padop, op_padix),},/*16*/
+ { STR_WITH_LEN("cop_seq"), U32p, STRUCT_OFFSET(struct cop, cop_seq), },/*17*/
+ { STR_WITH_LEN("line"), line_tp, STRUCT_OFFSET(struct cop, cop_line), },/*18*/
+ { STR_WITH_LEN("hints"), U32p, STRUCT_OFFSET(struct cop, cop_hints), },/*19*/
+#ifdef USE_ITHREADS
+ { STR_WITH_LEN("pmoffset"),IVp, STRUCT_OFFSET(struct pmop, op_pmoffset),},/*20*/
+ { STR_WITH_LEN("filegv"), op_offset_special, 0, },/*21*/
+ { STR_WITH_LEN("file"), char_pp, STRUCT_OFFSET(struct cop, cop_file), },/*22*/
+ { STR_WITH_LEN("stash"), op_offset_special, 0, },/*23*/
+ { STR_WITH_LEN("stashpv"), op_offset_special, 0, },/*24*/
+ { STR_WITH_LEN("stashoff"),PADOFFSETp,STRUCT_OFFSET(struct cop,cop_stashoff),},/*25*/
#else
- STR_WITH_LEN("code_list"),0, -1,
+ { STR_WITH_LEN("pmoffset"),op_offset_special, 0, },/*20*/
+ { STR_WITH_LEN("filegv"), SVp, STRUCT_OFFSET(struct cop, cop_filegv),},/*21*/
+ { STR_WITH_LEN("file"), op_offset_special, 0, },/*22*/
+ { STR_WITH_LEN("stash"), SVp, STRUCT_OFFSET(struct cop, cop_stash), },/*23*/
+ { STR_WITH_LEN("stashpv"), op_offset_special, 0, },/*24*/
+ { STR_WITH_LEN("stashoff"),op_offset_special, 0, },/*25*/
#endif
- STR_WITH_LEN("sv"), SVp, offsetof(struct svop, op_sv), /*14*/
- STR_WITH_LEN("gv"), SVp, offsetof(struct svop, op_sv), /*15*/
- STR_WITH_LEN("padix"), PADOFFSETp,offsetof(struct padop, op_padix),/*16*/
- STR_WITH_LEN("cop_seq"), U32p, offsetof(struct cop, cop_seq), /*17*/
- STR_WITH_LEN("line"), line_tp, offsetof(struct cop, cop_line), /*18*/
- STR_WITH_LEN("hints"), U32p, offsetof(struct cop, cop_hints), /*19*/
-#ifdef USE_ITHREADS
- STR_WITH_LEN("pmoffset"),IVp, offsetof(struct pmop, op_pmoffset),/*20*/
- STR_WITH_LEN("filegv"), 0, -1, /*21*/
- STR_WITH_LEN("file"), char_pp, offsetof(struct cop, cop_file), /*22*/
- STR_WITH_LEN("stash"), 0, -1, /*23*/
-# if PERL_VERSION < 17
- STR_WITH_LEN("stashpv"), char_pp, offsetof(struct cop, cop_stashpv), /*24*/
- STR_WITH_LEN("stashoff"),0, -1, /*25*/
+ { STR_WITH_LEN("size"), op_offset_special, 0, },/*26*/
+ { STR_WITH_LEN("name"), op_offset_special, 0, },/*27*/
+ { STR_WITH_LEN("desc"), op_offset_special, 0, },/*28*/
+ { STR_WITH_LEN("ppaddr"), op_offset_special, 0, },/*29*/
+ { STR_WITH_LEN("type"), op_offset_special, 0, },/*30*/
+ { STR_WITH_LEN("opt"), op_offset_special, 0, },/*31*/
+ { STR_WITH_LEN("spare"), op_offset_special, 0, },/*32*/
+ { STR_WITH_LEN("children"),op_offset_special, 0, },/*33*/
+ { STR_WITH_LEN("pmreplroot"), op_offset_special, 0, },/*34*/
+ { STR_WITH_LEN("pmstashpv"), op_offset_special, 0, },/*35*/
+ { STR_WITH_LEN("pmstash"), op_offset_special, 0, },/*36*/
+ { STR_WITH_LEN("precomp"), op_offset_special, 0, },/*37*/
+ { STR_WITH_LEN("reflags"), op_offset_special, 0, },/*38*/
+ { STR_WITH_LEN("sv"), op_offset_special, 0, },/*39*/
+ { STR_WITH_LEN("gv"), op_offset_special, 0, },/*40*/
+ { STR_WITH_LEN("pv"), op_offset_special, 0, },/*41*/
+ { STR_WITH_LEN("label"), op_offset_special, 0, },/*42*/
+ { STR_WITH_LEN("arybase"), op_offset_special, 0, },/*43*/
+ { STR_WITH_LEN("warnings"),op_offset_special, 0, },/*44*/
+ { STR_WITH_LEN("io"), op_offset_special, 0, },/*45*/
+ { STR_WITH_LEN("hints_hash"),op_offset_special, 0, },/*46*/
+ { STR_WITH_LEN("slabbed"), op_offset_special, 0, },/*47*/
+ { STR_WITH_LEN("savefree"),op_offset_special, 0, },/*48*/
+ { STR_WITH_LEN("static"), op_offset_special, 0, },/*49*/
+ { STR_WITH_LEN("folded"), op_offset_special, 0, },/*50*/
+ { STR_WITH_LEN("moresib"), op_offset_special, 0, },/*51*/
+ { STR_WITH_LEN("parent"), op_offset_special, 0, },/*52*/
+ { STR_WITH_LEN("first"), op_offset_special, 0, },/*53*/
+ { STR_WITH_LEN("meth_sv"), op_offset_special, 0, },/*54*/
+ { STR_WITH_LEN("pmregexp"),op_offset_special, 0, },/*55*/
+# ifdef USE_ITHREADS
+ { STR_WITH_LEN("rclass"), op_offset_special, 0, },/*56*/
# else
- STR_WITH_LEN("stashpv"), 0, -1, /*24*/
- STR_WITH_LEN("stashoff"),PADOFFSETp,offsetof(struct cop, cop_stashoff),/*25*/
+ { STR_WITH_LEN("rclass"), op_offset_special, 0, },/*56*/
# endif
-#else
- STR_WITH_LEN("pmoffset"),0, -1, /*20*/
- STR_WITH_LEN("filegv"), SVp, offsetof(struct cop, cop_filegv), /*21*/
- STR_WITH_LEN("file"), 0, -1, /*22*/
- STR_WITH_LEN("stash"), SVp, offsetof(struct cop, cop_stash), /*23*/
- STR_WITH_LEN("stashpv"), 0, -1, /*24*/
- STR_WITH_LEN("stashoff"),0, -1, /*25*/
-#endif
- STR_WITH_LEN("size"), 0, -1, /*26*/
- STR_WITH_LEN("name"), 0, -1, /*27*/
- STR_WITH_LEN("desc"), 0, -1, /*28*/
- STR_WITH_LEN("ppaddr"), 0, -1, /*29*/
- STR_WITH_LEN("type"), 0, -1, /*30*/
- STR_WITH_LEN("opt"), 0, -1, /*31*/
- STR_WITH_LEN("spare"), 0, -1, /*32*/
- STR_WITH_LEN("children"),0, -1, /*33*/
- STR_WITH_LEN("pmreplroot"), 0, -1, /*34*/
- STR_WITH_LEN("pmstashpv"), 0, -1, /*35*/
- STR_WITH_LEN("pmstash"), 0, -1, /*36*/
- STR_WITH_LEN("precomp"), 0, -1, /*37*/
- STR_WITH_LEN("reflags"), 0, -1, /*38*/
- STR_WITH_LEN("sv"), 0, -1, /*39*/
- STR_WITH_LEN("gv"), 0, -1, /*40*/
- STR_WITH_LEN("pv"), 0, -1, /*41*/
- STR_WITH_LEN("label"), 0, -1, /*42*/
- STR_WITH_LEN("arybase"), 0, -1, /*43*/
- STR_WITH_LEN("warnings"),0, -1, /*44*/
- STR_WITH_LEN("io"), 0, -1, /*45*/
- STR_WITH_LEN("hints_hash"),0, -1, /*46*/
};
#include "const-c.inc"
{
CV *cv;
const char *file = __FILE__;
+ SV *sv;
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] = (SV *) pWARN_ALL;
- specialsv_list[5] = (SV *) pWARN_NONE;
- specialsv_list[6] = (SV *) pWARN_STD;
-
+ B_init_my_cxt(aTHX_ &(MY_CXT));
cv = newXS("B::init_av", intrpvar_sv_common, file);
ASSIGN_COMMON_ALIAS(I, initav);
cv = newXS("B::check_av", intrpvar_sv_common, file);
ASSIGN_COMMON_ALIAS(I, warnhook);
cv = newXS("B::diehook", intrpvar_sv_common, file);
ASSIGN_COMMON_ALIAS(I, diehook);
+ sv = get_sv("B::OP::does_parent", GV_ADDMULTI);
+#ifdef PERL_OP_PARENT
+ sv_setsv(sv, &PL_sv_yes);
+#else
+ sv_setsv(sv, &PL_sv_no);
+#endif
}
#ifndef PL_formfeed
PPCODE:
+#ifdef USE_ITHREADS
+void
+CLONE(...)
+PPCODE:
+ PUTBACK; /* some vars go out of scope now in machine code */
+ {
+ MY_CXT_CLONE;
+ B_init_my_cxt(aTHX_ &(MY_CXT));
+ }
+ return; /* dont execute another implied XSPP PUTBACK */
+#endif
MODULE = B PACKAGE = B::OP
B::COP::warnings = 44
B::COP::io = 45
B::COP::hints_hash = 46
+ B::OP::slabbed = 47
+ B::OP::savefree = 48
+ B::OP::static = 49
+ B::OP::folded = 50
+ B::OP::moresib = 51
+ B::OP::parent = 52
+ B::METHOP::first = 53
+ B::METHOP::meth_sv = 54
+ B::PMOP::pmregexp = 55
+ B::METHOP::rclass = 56
PREINIT:
- char *ptr;
SV *ret;
- I32 type;
- I32 offset;
- STRLEN len;
PPCODE:
- if (ix < 0 || ix > 46)
+ if (ix < 0 || (U32)ix >= C_ARRAY_LENGTH(op_methods))
croak("Illegal alias %d for B::*OP::next", (int)ix);
ret = get_overlay_object(aTHX_ o,
op_methods[ix].name, op_methods[ix].namelen);
/* handle non-direct field access */
- offset = op_methods[ix].offset;
- if (offset < 0) {
+ if (op_methods[ix].type == op_offset_special)
switch (ix) {
- case 8: /* pmreplstart */
+ case 1: /* B::OP::op_sibling */
+ ret = make_op_object(aTHX_ OpSIBLING(o));
+ break;
+
+ case 8: /* B::PMOP::pmreplstart */
ret = make_op_object(aTHX_
cPMOPo->op_type == OP_SUBST
? cPMOPo->op_pmstashstartu.op_pmreplstart
);
break;
#ifdef USE_ITHREADS
- case 21: /* filegv */
+ case 21: /* B::COP::filegv */
ret = make_sv_object(aTHX_ (SV *)CopFILEGV((COP*)o));
break;
#endif
#ifndef USE_ITHREADS
- case 22: /* file */
+ case 22: /* B::COP::file */
ret = sv_2mortal(newSVpv(CopFILE((COP*)o), 0));
break;
#endif
#ifdef USE_ITHREADS
- case 23: /* stash */
+ case 23: /* B::COP::stash */
ret = make_sv_object(aTHX_ (SV *)CopSTASH((COP*)o));
break;
#endif
-#if PERL_VERSION >= 17 || !defined USE_ITHREADS
- case 24: /* stashpv */
-# if PERL_VERSION >= 17
+ case 24: /* B::COP::stashpv */
ret = sv_2mortal(CopSTASH((COP*)o)
&& SvTYPE(CopSTASH((COP*)o)) == SVt_PVHV
? newSVhek(HvNAME_HEK(CopSTASH((COP*)o)))
: &PL_sv_undef);
-# else
- ret = sv_2mortal(newSVpv(CopSTASHPV((COP*)o), 0));
-# endif
break;
-#endif
- case 26: /* size */
+ case 26: /* B::OP::size */
ret = sv_2mortal(newSVuv((UV)(opsizes[cc_opclass(aTHX_ o)])));
break;
- case 27: /* name */
- case 28: /* desc */
+ case 27: /* B::OP::name */
+ case 28: /* B::OP::desc */
ret = sv_2mortal(newSVpv(
(char *)(ix == 28 ? OP_DESC(o) : OP_NAME(o)), 0));
break;
- case 29: /* ppaddr */
+ case 29: /* B::OP::ppaddr */
{
int i;
ret = sv_2mortal(Perl_newSVpvf(aTHX_ "PL_ppaddr[OP_%s]",
SvPVX(ret)[i] = toUPPER(SvPVX(ret)[i]);
}
break;
- case 30: /* type */
- case 31: /* opt */
- case 32: /* spare */
- /* These 3 are all bitfields, so we can't take their addresses */
+ case 30: /* B::OP::type */
+ case 31: /* B::OP::opt */
+ case 32: /* B::OP::spare */
+ case 47: /* B::OP::slabbed */
+ case 48: /* B::OP::savefree */
+ case 49: /* B::OP::static */
+ case 50: /* B::OP::folded */
+ case 51: /* B::OP::moresib */
+ /* These are all bitfields, so we can't take their addresses */
ret = sv_2mortal(newSVuv((UV)(
ix == 30 ? o->op_type
: ix == 31 ? o->op_opt
+ : ix == 47 ? o->op_slabbed
+ : ix == 48 ? o->op_savefree
+ : ix == 49 ? o->op_static
+ : ix == 50 ? o->op_folded
+ : ix == 51 ? o->op_moresib
: o->op_spare)));
break;
- case 33: /* children */
+ case 33: /* B::LISTOP::children */
{
OP *kid;
UV i = 0;
- for (kid = ((LISTOP*)o)->op_first; kid; kid = kid->op_sibling)
+ for (kid = ((LISTOP*)o)->op_first; kid; kid = OpSIBLING(kid))
i++;
ret = sv_2mortal(newSVuv(i));
}
break;
- case 34: /* pmreplroot */
+ case 34: /* B::PMOP::pmreplroot */
if (cPMOPo->op_type == OP_PUSHRE) {
#ifdef USE_ITHREADS
ret = sv_newmortal();
}
break;
#ifdef USE_ITHREADS
- case 35: /* pmstashpv */
+ case 35: /* B::PMOP::pmstashpv */
ret = sv_2mortal(newSVpv(PmopSTASHPV(cPMOPo),0));
break;
#else
- case 36: /* pmstash */
+ case 36: /* B::PMOP::pmstash */
ret = make_sv_object(aTHX_ (SV *) PmopSTASH(cPMOPo));
break;
#endif
- case 37: /* precomp */
- case 38: /* reflags */
+ case 37: /* B::PMOP::precomp */
+ case 38: /* B::PMOP::reflags */
{
REGEXP *rx = PM_GETRE(cPMOPo);
ret = sv_newmortal();
}
else {
sv_setpvn(ret, RX_PRECOMP(rx), RX_PRELEN(rx));
+ if (RX_UTF8(rx))
+ SvUTF8_on(ret);
}
}
}
break;
- case 39: /* sv */
- case 40: /* gv */
- /* It happens that the output typemaps for B::SV and B::GV
- * are identical. The "smarts" are in make_sv_object(),
- * which determines which class to use based on SvTYPE(),
- * rather than anything baked in at compile time. */
- if (cPADOPo->op_padix) {
- ret = PAD_SVl(cPADOPo->op_padix);
- if (ix == 40 && SvTYPE(ret) != SVt_PVGV)
- ret = NULL;
- } else {
- ret = NULL;
- }
- ret = make_sv_object(aTHX_ ret);
+ case 39: /* B::PADOP::sv */
+ case 40: /* B::PADOP::gv */
+ /* PADOPs should only be created on threaded builds.
+ * They don't have an sv or gv field, just an op_padix
+ * field. Leave it to the caller to retrieve padix
+ * and look up th value in the pad. Don't do it here,
+ * becuase PL_curpad is the pad of the caller, not the
+ * pad of the sub the op is part of */
+ ret = make_sv_object(aTHX_ NULL);
break;
- case 41: /* pv */
+ case 41: /* B::PVOP::pv */
/* OP_TRANS uses op_pv to point to a table of 256 or >=258
* shorts whereas other PVOPs point to a null terminated
* string. */
else
ret = newSVpvn_flags(cPVOPo->op_pv, strlen(cPVOPo->op_pv), SVs_TEMP);
break;
- case 42: /* label */
+ case 42: /* B::COP::label */
ret = sv_2mortal(newSVpv(CopLABEL(cCOPo),0));
break;
- case 43: /* arybase */
+ case 43: /* B::COP::arybase */
ret = sv_2mortal(newSVuv(0));
break;
- case 44: /* warnings */
+ case 44: /* B::COP::warnings */
ret = make_warnings_object(aTHX_ cCOPo);
break;
- case 45: /* io */
+ case 45: /* B::COP::io */
ret = make_cop_io_object(aTHX_ cCOPo);
break;
- case 46: /* hints_hash */
+ case 46: /* B::COP::hints_hash */
ret = sv_newmortal();
sv_setiv(newSVrv(ret, "B::RHE"),
PTR2IV(CopHINTHASH_get(cCOPo)));
break;
+ case 52: /* B::OP::parent */
+#ifdef PERL_OP_PARENT
+ ret = make_op_object(aTHX_ op_parent(o));
+#else
+ ret = make_op_object(aTHX_ NULL);
+#endif
+ break;
+ case 53: /* B::METHOP::first */
+ /* METHOP struct has an op_first/op_meth_sv union
+ * as its first extra field. How to interpret the
+ * union depends on the op type. For the purposes of
+ * B, we treat it as a struct with both fields present,
+ * where one of the fields always happens to be null
+ * (i.e. we return NULL in preference to croaking with
+ * 'method not implemented').
+ */
+ ret = make_op_object(aTHX_
+ o->op_type == OP_METHOD
+ ? cMETHOPx(o)->op_u.op_first : NULL);
+ break;
+ case 54: /* B::METHOP::meth_sv */
+ /* see comment above about METHOP */
+ ret = make_sv_object(aTHX_
+ o->op_type == OP_METHOD
+ ? NULL : cMETHOPx(o)->op_u.op_meth_sv);
+ break;
+ case 55: /* B::PMOP::pmregexp */
+ ret = make_sv_object(aTHX_ (SV *)PM_GETRE(cPMOPo));
+ break;
+ case 56: /* B::METHOP::rclass */
+#ifdef USE_ITHREADS
+ ret = sv_2mortal(newSVuv(
+ (o->op_type == OP_METHOD_REDIR ||
+ o->op_type == OP_METHOD_REDIR_SUPER) ?
+ cMETHOPx(o)->op_rclass_targ : 0
+ ));
+#else
+ ret = make_sv_object(aTHX_
+ (o->op_type == OP_METHOD_REDIR ||
+ o->op_type == OP_METHOD_REDIR_SUPER) ?
+ cMETHOPx(o)->op_rclass_sv : NULL
+ );
+#endif
+ break;
default:
croak("method %s not implemented", op_methods[ix].name);
+ } else {
+ /* do a direct structure offset lookup */
+ const char *const ptr = (char *)o + op_methods[ix].offset;
+ switch (op_methods[ix].type) {
+ case OPp:
+ ret = make_op_object(aTHX_ *((OP **)ptr));
+ break;
+ case PADOFFSETp:
+ ret = sv_2mortal(newSVuv(*((PADOFFSET*)ptr)));
+ break;
+ case U8p:
+ ret = sv_2mortal(newSVuv(*((U8*)ptr)));
+ break;
+ case U32p:
+ ret = sv_2mortal(newSVuv(*((U32*)ptr)));
+ break;
+ case SVp:
+ ret = make_sv_object(aTHX_ *((SV **)ptr));
+ break;
+ case line_tp:
+ ret = sv_2mortal(newSVuv(*((line_t *)ptr)));
+ break;
+ case IVp:
+ ret = sv_2mortal(newSViv(*((IV*)ptr)));
+ break;
+ case char_pp:
+ ret = sv_2mortal(newSVpv(*((char **)ptr), 0));
+ break;
+ default:
+ croak("Illegal type 0x%x for B::*OP::%s",
+ (unsigned)op_methods[ix].type, op_methods[ix].name);
}
- ST(0) = ret;
- XSRETURN(1);
- }
-
- /* do a direct structure offset lookup */
-
- ptr = (char *)o + offset;
- type = op_methods[ix].type;
- switch ((U8)(type >> 16)) {
- case (U8)(OPp >> 16):
- ret = make_op_object(aTHX_ *((OP **)ptr));
- break;
- case (U8)(PADOFFSETp >> 16):
- ret = sv_2mortal(newSVuv(*((PADOFFSET*)ptr)));
- break;
- case (U8)(U8p >> 16):
- ret = sv_2mortal(newSVuv(*((U8*)ptr)));
- break;
- case (U8)(U32p >> 16):
- ret = sv_2mortal(newSVuv(*((U32*)ptr)));
- break;
- case (U8)(SVp >> 16):
- ret = make_sv_object(aTHX_ *((SV **)ptr));
- break;
- case (U8)(line_tp >> 16):
- ret = sv_2mortal(newSVuv(*((line_t *)ptr)));
- break;
- case (U8)(IVp >> 16):
- ret = sv_2mortal(newSViv(*((IV*)ptr)));
- break;
- case (U8)(char_pp >> 16):
- ret = sv_2mortal(newSVpv(*((char **)ptr), 0));
- break;
- default:
- croak("Illegal type 0x%08x for B::*OP::%s",
- (unsigned)type, op_methods[ix].name);
-
}
ST(0) = ret;
XSRETURN(1);
SP = oplist(aTHX_ o, SP);
+
+MODULE = B PACKAGE = B::UNOP_AUX
+
+# UNOP_AUX class ops are like UNOPs except that they have an extra
+# op_aux pointer that points to an array of UNOP_AUX_item unions.
+# Element -1 of the array contains the length
+
+
+# return a string representation of op_aux where possible The op's CV is
+# needed as an extra arg to allow GVs and SVs moved into the pad to be
+# accessed okay.
+
+void
+string(o, cv)
+ B::OP o
+ B::CV cv
+ PREINIT:
+ SV *ret;
+ UNOP_AUX_item *aux;
+ PPCODE:
+ aux = cUNOP_AUXo->op_aux;
+ switch (o->op_type) {
+ case OP_MULTIDEREF:
+ ret = multideref_stringify(o, cv);
+ break;
+
+ case OP_ARGELEM:
+ ret = sv_2mortal(Perl_newSVpvf(aTHX_ "%"UVuf,
+ PTR2UV(aux)));
+ break;
+
+ case OP_ARGCHECK:
+ ret = Perl_newSVpvf(aTHX_ "%"UVuf",%"UVuf, aux[0].uv, aux[1].uv);
+ if (aux[2].iv)
+ Perl_sv_catpvf(aTHX_ ret, ",%c", (char)aux[2].iv);
+ ret = sv_2mortal(ret);
+ break;
+
+ default:
+ ret = sv_2mortal(newSVpvn("", 0));
+ }
+
+ ST(0) = ret;
+ XSRETURN(1);
+
+
+# Return the contents of the op_aux array as a list of IV/GV/etc objects.
+# How to interpret each array element is op-dependent. The op's CV is
+# needed as an extra arg to allow GVs and SVs which have been moved into
+# the pad to be accessed okay.
+
+void
+aux_list(o, cv)
+ B::OP o
+ B::CV cv
+ PREINIT:
+ UNOP_AUX_item *aux;
+ PPCODE:
+ PERL_UNUSED_VAR(cv); /* not needed on unthreaded builds */
+ aux = cUNOP_AUXo->op_aux;
+ switch (o->op_type) {
+ default:
+ XSRETURN(0); /* by default, an empty list */
+
+ case OP_ARGELEM:
+ XPUSHs(sv_2mortal(newSVuv(PTR2UV(aux))));
+ XSRETURN(1);
+ break;
+
+ case OP_ARGCHECK:
+ EXTEND(SP, 3);
+ PUSHs(sv_2mortal(newSVuv(aux[0].uv)));
+ PUSHs(sv_2mortal(newSVuv(aux[1].uv)));
+ PUSHs(sv_2mortal(aux[2].iv ? Perl_newSVpvf(aTHX_ "%c",
+ (char)aux[2].iv) : &PL_sv_no));
+ break;
+
+ case OP_MULTIDEREF:
+#ifdef USE_ITHREADS
+# define ITEM_SV(item) *av_fetch(comppad, (item)->pad_offset, FALSE);
+#else
+# define ITEM_SV(item) UNOP_AUX_item_sv(item)
+#endif
+ {
+ UNOP_AUX_item *items = cUNOP_AUXo->op_aux;
+ UV actions = items->uv;
+ UV len = items[-1].uv;
+ SV *sv;
+ bool last = 0;
+ bool is_hash = FALSE;
+#ifdef USE_ITHREADS
+ PADLIST * const padlist = CvPADLIST(cv);
+ PAD *comppad = PadlistARRAY(padlist)[1];
+#endif
+
+ /* len should never be big enough to truncate or wrap */
+ assert(len <= SSize_t_MAX);
+ EXTEND(SP, (SSize_t)len);
+ PUSHs(sv_2mortal(newSViv(actions)));
+
+ while (!last) {
+ switch (actions & MDEREF_ACTION_MASK) {
+
+ case MDEREF_reload:
+ actions = (++items)->uv;
+ PUSHs(sv_2mortal(newSVuv(actions)));
+ continue;
+ NOT_REACHED; /* NOTREACHED */
+
+ case MDEREF_HV_padhv_helem:
+ is_hash = TRUE;
+ /* FALLTHROUGH */
+ case MDEREF_AV_padav_aelem:
+ PUSHs(sv_2mortal(newSVuv((++items)->pad_offset)));
+ goto do_elem;
+ NOT_REACHED; /* NOTREACHED */
+
+ case MDEREF_HV_gvhv_helem:
+ is_hash = TRUE;
+ /* FALLTHROUGH */
+ case MDEREF_AV_gvav_aelem:
+ sv = ITEM_SV(++items);
+ PUSHs(make_sv_object(aTHX_ sv));
+ goto do_elem;
+ NOT_REACHED; /* NOTREACHED */
+
+ case MDEREF_HV_gvsv_vivify_rv2hv_helem:
+ is_hash = TRUE;
+ /* FALLTHROUGH */
+ case MDEREF_AV_gvsv_vivify_rv2av_aelem:
+ sv = ITEM_SV(++items);
+ PUSHs(make_sv_object(aTHX_ sv));
+ goto do_vivify_rv2xv_elem;
+ NOT_REACHED; /* NOTREACHED */
+
+ case MDEREF_HV_padsv_vivify_rv2hv_helem:
+ is_hash = TRUE;
+ /* FALLTHROUGH */
+ case MDEREF_AV_padsv_vivify_rv2av_aelem:
+ PUSHs(sv_2mortal(newSVuv((++items)->pad_offset)));
+ goto do_vivify_rv2xv_elem;
+ NOT_REACHED; /* NOTREACHED */
+
+ case MDEREF_HV_pop_rv2hv_helem:
+ case MDEREF_HV_vivify_rv2hv_helem:
+ is_hash = TRUE;
+ /* FALLTHROUGH */
+ do_vivify_rv2xv_elem:
+ case MDEREF_AV_pop_rv2av_aelem:
+ case MDEREF_AV_vivify_rv2av_aelem:
+ do_elem:
+ switch (actions & MDEREF_INDEX_MASK) {
+ case MDEREF_INDEX_none:
+ last = 1;
+ break;
+ case MDEREF_INDEX_const:
+ if (is_hash) {
+ sv = ITEM_SV(++items);
+ PUSHs(make_sv_object(aTHX_ sv));
+ }
+ else
+ PUSHs(sv_2mortal(newSViv((++items)->iv)));
+ break;
+ case MDEREF_INDEX_padsv:
+ PUSHs(sv_2mortal(newSVuv((++items)->pad_offset)));
+ break;
+ case MDEREF_INDEX_gvsv:
+ sv = ITEM_SV(++items);
+ PUSHs(make_sv_object(aTHX_ sv));
+ break;
+ }
+ if (actions & MDEREF_FLAG_last)
+ last = 1;
+ is_hash = FALSE;
+
+ break;
+ } /* switch */
+
+ actions >>= MDEREF_SHIFT;
+ } /* while */
+ XSRETURN(len);
+
+ } /* OP_MULTIDEREF */
+ } /* switch */
+
+
+
MODULE = B PACKAGE = B::SV
#define MAGICAL_FLAG_BITS (SVs_GMG|SVs_SMG|SVs_RMG)
#define sv_I32p 0xA0000
#define sv_U16p 0xB0000
-#define IV_ivx_ix sv_IVp | offsetof(struct xpviv, xiv_iv)
-#define IV_uvx_ix sv_UVp | offsetof(struct xpvuv, xuv_uv)
-#define NV_nvx_ix sv_NVp | offsetof(struct xpvnv, xnv_u.xnv_nv)
+#define IV_ivx_ix sv_IVp | STRUCT_OFFSET(struct xpviv, xiv_iv)
+#define IV_uvx_ix sv_UVp | STRUCT_OFFSET(struct xpvuv, xuv_uv)
+#define NV_nvx_ix sv_NVp | STRUCT_OFFSET(struct xpvnv, xnv_u.xnv_nv)
-#define NV_cop_seq_range_low_ix \
- sv_U32p | offsetof(struct xpvnv, xnv_u.xpad_cop_seq.xlow)
-#define NV_cop_seq_range_high_ix \
- sv_U32p | offsetof(struct xpvnv, xnv_u.xpad_cop_seq.xhigh)
-#define NV_parent_pad_index_ix \
- sv_U32p | offsetof(struct xpvnv, xnv_u.xpad_cop_seq.xlow)
-#define NV_parent_fakelex_flags_ix \
- sv_U32p | offsetof(struct xpvnv, xnv_u.xpad_cop_seq.xhigh)
+#define PV_cur_ix sv_STRLENp | STRUCT_OFFSET(struct xpv, xpv_cur)
+#define PV_len_ix sv_STRLENp | STRUCT_OFFSET(struct xpv, xpv_len)
-#define PV_cur_ix sv_STRLENp | offsetof(struct xpv, xpv_cur)
-#define PV_len_ix sv_STRLENp | offsetof(struct xpv, xpv_len)
+#define PVMG_stash_ix sv_SVp | STRUCT_OFFSET(struct xpvmg, xmg_stash)
-#define PVMG_stash_ix sv_SVp | offsetof(struct xpvmg, xmg_stash)
+#define PVBM_useful_ix sv_IVp | STRUCT_OFFSET(struct xpviv, xiv_u.xivu_iv)
-#if PERL_VERSION > 18
-# define PVBM_useful_ix sv_I32p | offsetof(struct xpvgv, xnv_u.xbm_useful)
-#elif PERL_VERSION > 14
-# define PVBM_useful_ix sv_I32p | offsetof(struct xpvgv, xnv_u.xbm_s.xbm_useful)
-#else
-#define PVBM_useful_ix sv_I32p | offsetof(struct xpvgv, xiv_u.xivu_i32)
-#endif
+#define PVLV_targoff_ix sv_U32p | STRUCT_OFFSET(struct xpvlv, xlv_targoff)
+#define PVLV_targlen_ix sv_U32p | STRUCT_OFFSET(struct xpvlv, xlv_targlen)
+#define PVLV_targ_ix sv_SVp | STRUCT_OFFSET(struct xpvlv, xlv_targ)
+#define PVLV_type_ix sv_char_p | STRUCT_OFFSET(struct xpvlv, xlv_type)
-#define PVLV_targoff_ix sv_U32p | offsetof(struct xpvlv, xlv_targoff)
-#define PVLV_targlen_ix sv_U32p | offsetof(struct xpvlv, xlv_targlen)
-#define PVLV_targ_ix sv_SVp | offsetof(struct xpvlv, xlv_targ)
-#define PVLV_type_ix sv_char_p | offsetof(struct xpvlv, xlv_type)
-
-#define PVGV_stash_ix sv_SVp | offsetof(struct xpvgv, xnv_u.xgv_stash)
-#define PVGV_flags_ix sv_STRLENp | offsetof(struct xpvgv, xpv_cur)
-#define PVIO_lines_ix sv_IVp | offsetof(struct xpvio, xiv_iv)
-
-#define PVIO_page_ix sv_IVp | offsetof(struct xpvio, xio_page)
-#define PVIO_page_len_ix sv_IVp | offsetof(struct xpvio, xio_page_len)
-#define PVIO_lines_left_ix sv_IVp | offsetof(struct xpvio, xio_lines_left)
-#define PVIO_top_name_ix sv_char_pp | offsetof(struct xpvio, xio_top_name)
-#define PVIO_top_gv_ix sv_SVp | offsetof(struct xpvio, xio_top_gv)
-#define PVIO_fmt_name_ix sv_char_pp | offsetof(struct xpvio, xio_fmt_name)
-#define PVIO_fmt_gv_ix sv_SVp | offsetof(struct xpvio, xio_fmt_gv)
-#define PVIO_bottom_name_ix sv_char_pp | offsetof(struct xpvio, xio_bottom_name)
-#define PVIO_bottom_gv_ix sv_SVp | offsetof(struct xpvio, xio_bottom_gv)
-#define PVIO_type_ix sv_char_p | offsetof(struct xpvio, xio_type)
-#define PVIO_flags_ix sv_U8p | offsetof(struct xpvio, xio_flags)
-
-#define PVAV_max_ix sv_SSize_tp | offsetof(struct xpvav, xav_max)
-
-#define PVCV_stash_ix sv_SVp | offsetof(struct xpvcv, xcv_stash)
-#if PERL_VERSION > 17 || (PERL_VERSION == 17 && PERL_SUBVERSION >= 3)
-# define PVCV_gv_ix sv_SVp | offsetof(struct xpvcv, xcv_gv_u.xcv_gv)
-#else
-# define PVCV_gv_ix sv_SVp | offsetof(struct xpvcv, xcv_gv)
-#endif
-#define PVCV_file_ix sv_char_pp | offsetof(struct xpvcv, xcv_file)
-#define PVCV_outside_ix sv_SVp | offsetof(struct xpvcv, xcv_outside)
-#define PVCV_outside_seq_ix sv_U32p | offsetof(struct xpvcv, xcv_outside_seq)
-#define PVCV_flags_ix sv_U32p | offsetof(struct xpvcv, xcv_flags)
+#define PVGV_stash_ix sv_SVp | STRUCT_OFFSET(struct xpvgv, xnv_u.xgv_stash)
+#define PVGV_flags_ix sv_STRLENp | STRUCT_OFFSET(struct xpvgv, xpv_cur)
+#define PVIO_lines_ix sv_IVp | STRUCT_OFFSET(struct xpvio, xiv_iv)
-#define PVHV_max_ix sv_STRLENp | offsetof(struct xpvhv, xhv_max)
+#define PVIO_page_ix sv_IVp | STRUCT_OFFSET(struct xpvio, xio_page)
+#define PVIO_page_len_ix sv_IVp | STRUCT_OFFSET(struct xpvio, xio_page_len)
+#define PVIO_lines_left_ix sv_IVp | STRUCT_OFFSET(struct xpvio, xio_lines_left)
+#define PVIO_top_name_ix sv_char_pp | STRUCT_OFFSET(struct xpvio, xio_top_name)
+#define PVIO_top_gv_ix sv_SVp | STRUCT_OFFSET(struct xpvio, xio_top_gv)
+#define PVIO_fmt_name_ix sv_char_pp | STRUCT_OFFSET(struct xpvio, xio_fmt_name)
+#define PVIO_fmt_gv_ix sv_SVp | STRUCT_OFFSET(struct xpvio, xio_fmt_gv)
+#define PVIO_bottom_name_ix sv_char_pp | STRUCT_OFFSET(struct xpvio, xio_bottom_name)
+#define PVIO_bottom_gv_ix sv_SVp | STRUCT_OFFSET(struct xpvio, xio_bottom_gv)
+#define PVIO_type_ix sv_char_p | STRUCT_OFFSET(struct xpvio, xio_type)
+#define PVIO_flags_ix sv_U8p | STRUCT_OFFSET(struct xpvio, xio_flags)
-#if PERL_VERSION > 12
-#define PVHV_keys_ix sv_STRLENp | offsetof(struct xpvhv, xhv_keys)
-#else
-#define PVHV_keys_ix sv_IVp | offsetof(struct xpvhv, xhv_keys)
-#endif
+#define PVAV_max_ix sv_SSize_tp | STRUCT_OFFSET(struct xpvav, xav_max)
+
+#define PVCV_stash_ix sv_SVp | STRUCT_OFFSET(struct xpvcv, xcv_stash)
+#define PVCV_gv_ix sv_SVp | STRUCT_OFFSET(struct xpvcv, xcv_gv_u.xcv_gv)
+#define PVCV_file_ix sv_char_pp | STRUCT_OFFSET(struct xpvcv, xcv_file)
+#define PVCV_outside_ix sv_SVp | STRUCT_OFFSET(struct xpvcv, xcv_outside)
+#define PVCV_outside_seq_ix sv_U32p | STRUCT_OFFSET(struct xpvcv, xcv_outside_seq)
+#define PVCV_flags_ix sv_U32p | STRUCT_OFFSET(struct xpvcv, xcv_flags)
+
+#define PVHV_max_ix sv_STRLENp | STRUCT_OFFSET(struct xpvhv, xhv_max)
+#define PVHV_keys_ix sv_STRLENp | STRUCT_OFFSET(struct xpvhv, xhv_keys)
# The type checking code in B has always been identical for all SV types,
# irrespective of whether the action is actually defined on that SV.
B::IV::IVX = IV_ivx_ix
B::IV::UVX = IV_uvx_ix
B::NV::NVX = NV_nvx_ix
- B::NV::COP_SEQ_RANGE_LOW = NV_cop_seq_range_low_ix
- B::NV::COP_SEQ_RANGE_HIGH = NV_cop_seq_range_high_ix
- B::NV::PARENT_PAD_INDEX = NV_parent_pad_index_ix
- B::NV::PARENT_FAKELEX_FLAGS = NV_parent_fakelex_flags_ix
B::PV::CUR = PV_cur_ix
B::PV::LEN = PV_len_ix
B::PVMG::SvSTASH = PVMG_stash_ix
B::IO::IoFLAGS = PVIO_flags_ix
B::AV::MAX = PVAV_max_ix
B::CV::STASH = PVCV_stash_ix
- B::CV::GV = PVCV_gv_ix
B::CV::FILE = PVCV_file_ix
B::CV::OUTSIDE = PVCV_outside_ix
B::CV::OUTSIDE_SEQ = PVCV_outside_seq_ix
SvNV(sv)
B::NV sv
-#if PERL_VERSION < 11
-
-MODULE = B PACKAGE = B::RV PREFIX = Sv
-
-void
-SvRV(sv)
- B::RV sv
- PPCODE:
- PUSHs(make_sv_object(aTHX_ SvRV(sv)));
-
-#else
-
MODULE = B PACKAGE = B::REGEXP
void
B::REGEXP sv
ALIAS:
precomp = 1
+ qr_anoncv = 2
+ compflags = 3
PPCODE:
- if (ix) {
+ if (ix == 1) {
PUSHs(newSVpvn_flags(RX_PRECOMP(sv), RX_PRELEN(sv), SVs_TEMP));
+ } else if (ix == 2) {
+ PUSHs(make_sv_object(aTHX_ (SV *)ReANY(sv)->qr_anoncv));
} else {
dXSTARG;
+ if (ix)
+ PUSHu(RX_COMPFLAGS(sv));
+ else
/* FIXME - can we code this method more efficiently? */
- PUSHi(PTR2IV(sv));
+ PUSHi(PTR2IV(sv));
}
-#endif
-
MODULE = B PACKAGE = B::PV
void
U32
BmPREVIOUS(sv)
B::BM sv
+ CODE:
+ PERL_UNUSED_VAR(sv);
+ RETVAL = BmPREVIOUS(sv);
+ OUTPUT:
+ RETVAL
+
U8
BmRARE(sv)
B::BM sv
+ CODE:
+ PERL_UNUSED_VAR(sv);
+ RETVAL = BmRARE(sv);
+ OUTPUT:
+ RETVAL
+
MODULE = B PACKAGE = B::GV PREFIX = Gv
GvGP(gv)
B::GV gv
-#define GP_sv_ix SVp | offsetof(struct gp, gp_sv)
-#define GP_io_ix SVp | offsetof(struct gp, gp_io)
-#define GP_cv_ix SVp | offsetof(struct gp, gp_cv)
-#define GP_cvgen_ix U32p | offsetof(struct gp, gp_cvgen)
-#define GP_refcnt_ix U32p | offsetof(struct gp, gp_refcnt)
-#define GP_hv_ix SVp | offsetof(struct gp, gp_hv)
-#define GP_av_ix SVp | offsetof(struct gp, gp_av)
-#define GP_form_ix SVp | offsetof(struct gp, gp_form)
-#define GP_egv_ix SVp | offsetof(struct gp, gp_egv)
-#define GP_line_ix line_tp | offsetof(struct gp, gp_line)
+#define GP_sv_ix (SVp << 16) | STRUCT_OFFSET(struct gp, gp_sv)
+#define GP_io_ix (SVp << 16) | STRUCT_OFFSET(struct gp, gp_io)
+#define GP_cv_ix (SVp << 16) | STRUCT_OFFSET(struct gp, gp_cv)
+#define GP_cvgen_ix (U32p << 16) | STRUCT_OFFSET(struct gp, gp_cvgen)
+#define GP_refcnt_ix (U32p << 16) | STRUCT_OFFSET(struct gp, gp_refcnt)
+#define GP_hv_ix (SVp << 16) | STRUCT_OFFSET(struct gp, gp_hv)
+#define GP_av_ix (SVp << 16) | STRUCT_OFFSET(struct gp, gp_av)
+#define GP_form_ix (SVp << 16) | STRUCT_OFFSET(struct gp, gp_form)
+#define GP_egv_ix (SVp << 16) | STRUCT_OFFSET(struct gp, gp_egv)
void
SV(gv)
AV = GP_av_ix
FORM = GP_form_ix
EGV = GP_egv_ix
- LINE = GP_line_ix
PREINIT:
GP *gp;
char *ptr;
}
ptr = (ix & 0xFFFF) + (char *)gp;
switch ((U8)(ix >> 16)) {
- case (U8)(SVp >> 16):
+ case SVp:
ret = make_sv_object(aTHX_ *((SV **)ptr));
break;
- case (U8)(U32p >> 16):
+ case U32p:
ret = sv_2mortal(newSVuv(*((U32*)ptr)));
break;
- case (U8)(line_tp >> 16):
- ret = sv_2mortal(newSVuv(*((line_t *)ptr)));
- break;
default:
croak("Illegal alias 0x%08x for B::*SV", (unsigned)ix);
}
ST(0) = ret;
XSRETURN(1);
+U32
+GvLINE(gv)
+ B::GV gv
+
+U32
+GvGPFLAGS(gv)
+ B::GV gv
+
void
FILEGV(gv)
B::GV gv
MODULE = B PACKAGE = B::FM PREFIX = Fm
-#undef FmLINES
-#define FmLINES(sv) 0
-
IV
-FmLINES(form)
- B::FM form
+FmLINES(format)
+ B::FM format
+ CODE:
+ PERL_UNUSED_VAR(format);
+ RETVAL = 0;
+ OUTPUT:
+ RETVAL
+
MODULE = B PACKAGE = B::CV PREFIX = Cv
B::PADLIST
CvPADLIST(cv)
B::CV cv
+ CODE:
+ RETVAL = CvISXSUB(cv) ? NULL : CvPADLIST(cv);
+ OUTPUT:
+ RETVAL
#else
#endif
+SV *
+CvHSCXT(cv)
+ B::CV cv
+ CODE:
+ RETVAL = newSVuv(CvISXSUB(cv) ? PTR2UV(CvHSCXT(cv)) : 0);
+ OUTPUT:
+ RETVAL
+
void
CvXSUB(cv)
B::CV cv
PPCODE:
PUSHs(make_sv_object(aTHX_ (SV *)cv_const_sv(cv)));
+void
+GV(cv)
+ B::CV cv
+ CODE:
+ ST(0) = make_sv_object(aTHX_ (SV*)CvGV(cv));
+
+SV *
+NAME_HEK(cv)
+ B::CV cv
+ CODE:
+ RETVAL = CvNAMED(cv) ? newSVhek(CvNAME_HEK(cv)) : &PL_sv_undef;
+ OUTPUT:
+ RETVAL
+
MODULE = B PACKAGE = B::HV PREFIX = Hv
STRLEN
B::HV hv
PPCODE:
if (HvUSEDKEYS(hv) > 0) {
- SV *sv;
- char *key;
- I32 len;
+ HE *he;
+ SSize_t extend_size;
(void)hv_iterinit(hv);
- EXTEND(sp, HvUSEDKEYS(hv) * 2);
- while ((sv = hv_iternextsv(hv, &key, &len))) {
- mPUSHp(key, len);
- PUSHs(make_sv_object(aTHX_ sv));
+ /* 2*HvUSEDKEYS() should never be big enough to truncate or wrap */
+ assert(HvUSEDKEYS(hv) <= (SSize_t_MAX >> 1));
+ extend_size = (SSize_t)HvUSEDKEYS(hv) * 2;
+ EXTEND(sp, extend_size);
+ while ((he = hv_iternext(hv))) {
+ if (HeSVKEY(he)) {
+ mPUSHs(HeSVKEY(he));
+ } else if (HeKUTF8(he)) {
+ PUSHs(newSVpvn_flags(HeKEY(he), HeKLEN(he), SVf_UTF8|SVs_TEMP));
+ } else {
+ mPUSHp(HeKEY(he), HeKLEN(he));
+ }
+ PUSHs(make_sv_object(aTHX_ HeVAL(he)));
}
}
SSize_t
PadlistMAX(padlist)
B::PADLIST padlist
+ ALIAS: B::PADNAMELIST::MAX = 0
+ CODE:
+ PERL_UNUSED_VAR(ix);
+ RETVAL = PadlistMAX(padlist);
+ OUTPUT:
+ RETVAL
+
+B::PADNAMELIST
+PadlistNAMES(padlist)
+ B::PADLIST padlist
void
PadlistARRAY(padlist)
B::PADLIST padlist
PPCODE:
if (PadlistMAX(padlist) >= 0) {
+ dXSTARG;
PAD **padp = PadlistARRAY(padlist);
- PADOFFSET i;
- for (i = 0; i <= PadlistMAX(padlist); i++)
+ SSize_t i;
+ sv_setiv(newSVrv(TARG, PadlistNAMES(padlist)
+ ? "B::PADNAMELIST"
+ : "B::NULL"),
+ PTR2IV(PadlistNAMES(padlist)));
+ XPUSHTARG;
+ for (i = 1; i <= PadlistMAX(padlist); i++)
XPUSHs(make_sv_object(aTHX_ (SV *)padp[i]));
}
void
PadlistARRAYelt(padlist, idx)
B::PADLIST padlist
- PADOFFSET idx
+ SSize_t idx
PPCODE:
- if (PadlistMAX(padlist) >= 0
- && idx <= PadlistMAX(padlist))
+ if (idx < 0 || idx > PadlistMAX(padlist))
+ XPUSHs(make_sv_object(aTHX_ NULL));
+ else if (!idx) {
+ PL_stack_sp--;
+ PUSHMARK(PL_stack_sp-1);
+ XS_B__PADLIST_NAMES(aTHX_ cv);
+ return;
+ }
+ else
XPUSHs(make_sv_object(aTHX_
(SV *)PadlistARRAY(padlist)[idx]));
- else
- XPUSHs(make_sv_object(aTHX_ NULL));
U32
PadlistREFCNT(padlist)
B::PADLIST padlist
CODE:
+ PERL_UNUSED_VAR(padlist);
RETVAL = PadlistREFCNT(padlist);
OUTPUT:
RETVAL
#endif
+
+MODULE = B PACKAGE = B::PADNAMELIST PREFIX = Padnamelist
+
+void
+PadnamelistARRAY(pnl)
+ B::PADNAMELIST pnl
+ PPCODE:
+ if (PadnamelistMAX(pnl) >= 0) {
+ PADNAME **padp = PadnamelistARRAY(pnl);
+ SSize_t i = 0;
+ for (; i <= PadnamelistMAX(pnl); i++)
+ {
+ SV *rv = sv_newmortal();
+ sv_setiv(newSVrv(rv,padp[i] ? "B::PADNAME" : "B::SPECIAL"),
+ PTR2IV(padp[i]));
+ XPUSHs(rv);
+ }
+ }
+
+B::PADNAME
+PadnamelistARRAYelt(pnl, idx)
+ B::PADNAMELIST pnl
+ SSize_t idx
+ CODE:
+ if (idx < 0 || idx > PadnamelistMAX(pnl))
+ RETVAL = NULL;
+ else
+ RETVAL = PadnamelistARRAY(pnl)[idx];
+ OUTPUT:
+ RETVAL
+
+MODULE = B PACKAGE = B::PADNAME PREFIX = Padname
+
+#define PN_type_ix \
+ sv_SVp | STRUCT_OFFSET(struct padname,xpadn_type_u.xpadn_typestash)
+#define PN_ourstash_ix \
+ sv_SVp | STRUCT_OFFSET(struct padname,xpadn_ourstash)
+#define PN_len_ix \
+ sv_U8p | STRUCT_OFFSET(struct padname,xpadn_len)
+#define PN_refcnt_ix \
+ sv_U32p | STRUCT_OFFSET(struct padname, xpadn_refcnt)
+#define PN_cop_seq_range_low_ix \
+ sv_U32p | STRUCT_OFFSET(struct padname, xpadn_low)
+#define PN_cop_seq_range_high_ix \
+ sv_U32p | STRUCT_OFFSET(struct padname, xpadn_high)
+#define PNL_refcnt_ix \
+ sv_U32p | STRUCT_OFFSET(struct padnamelist, xpadnl_refcnt)
+#define PL_id_ix \
+ sv_U32p | STRUCT_OFFSET(struct padlist, xpadl_id)
+#define PL_outid_ix \
+ sv_U32p | STRUCT_OFFSET(struct padlist, xpadl_outid)
+
+
+void
+PadnameTYPE(pn)
+ B::PADNAME pn
+ ALIAS:
+ B::PADNAME::TYPE = PN_type_ix
+ B::PADNAME::OURSTASH = PN_ourstash_ix
+ B::PADNAME::LEN = PN_len_ix
+ B::PADNAME::REFCNT = PN_refcnt_ix
+ B::PADNAME::COP_SEQ_RANGE_LOW = PN_cop_seq_range_low_ix
+ B::PADNAME::COP_SEQ_RANGE_HIGH = PN_cop_seq_range_high_ix
+ B::PADNAMELIST::REFCNT = PNL_refcnt_ix
+ B::PADLIST::id = PL_id_ix
+ B::PADLIST::outid = PL_outid_ix
+ PREINIT:
+ char *ptr;
+ SV *ret;
+ PPCODE:
+ ptr = (ix & 0xFFFF) + (char *)pn;
+ switch ((U8)(ix >> 16)) {
+ case (U8)(sv_SVp >> 16):
+ ret = make_sv_object(aTHX_ *((SV **)ptr));
+ break;
+ case (U8)(sv_U32p >> 16):
+ ret = sv_2mortal(newSVuv(*((U32 *)ptr)));
+ break;
+ case (U8)(sv_U8p >> 16):
+ ret = sv_2mortal(newSVuv(*((U8 *)ptr)));
+ break;
+ default:
+ NOT_REACHED;
+ }
+ ST(0) = ret;
+ XSRETURN(1);
+
+SV *
+PadnamePV(pn)
+ B::PADNAME pn
+ PREINIT:
+ dXSTARG;
+ PPCODE:
+ PERL_UNUSED_ARG(RETVAL);
+ sv_setpvn(TARG, PadnamePV(pn), PadnameLEN(pn));
+ SvUTF8_on(TARG);
+ XPUSHTARG;
+
+BOOT:
+{
+ /* Uses less memory than an ALIAS. */
+ GV *gv = gv_fetchpvs("B::PADNAME::TYPE", 1, SVt_PVGV);
+ sv_setsv((SV *)gv_fetchpvs("B::PADNAME::SvSTASH",1,SVt_PVGV),(SV *)gv);
+ sv_setsv((SV *)gv_fetchpvs("B::PADNAME::PROTOCV",1,SVt_PVGV),(SV *)gv);
+ sv_setsv((SV *)gv_fetchpvs("B::PADNAME::PVX",1,SVt_PVGV),
+ (SV *)gv_fetchpvs("B::PADNAME::PV" ,1,SVt_PVGV));
+ sv_setsv((SV *)gv_fetchpvs("B::PADNAME::PARENT_PAD_INDEX" ,1,SVt_PVGV),
+ (SV *)gv_fetchpvs("B::PADNAME::COP_SEQ_RANGE_LOW",1,
+ SVt_PVGV));
+ sv_setsv((SV *)gv_fetchpvs("B::PADNAME::PARENT_FAKELEX_FLAGS",1,
+ SVt_PVGV),
+ (SV *)gv_fetchpvs("B::PADNAME::COP_SEQ_RANGE_HIGH" ,1,
+ SVt_PVGV));
+}
+
+U32
+PadnameFLAGS(pn)
+ B::PADNAME pn
+ CODE:
+ RETVAL = PadnameFLAGS(pn);
+ /* backward-compatibility hack, which should be removed if the
+ flags field becomes large enough to hold SVf_FAKE (and
+ PADNAMEt_OUTER should be renumbered to match SVf_FAKE) */
+ STATIC_ASSERT_STMT(SVf_FAKE >= 1<<(sizeof(PadnameFLAGS((B__PADNAME)NULL)) * 8));
+ if (PadnameOUTER(pn))
+ RETVAL |= SVf_FAKE;
+ OUTPUT:
+ RETVAL