X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/e6070cd609a1c2bf6abe7cb73ab39e0af43355f1..9fdb8483d0df6457614b48340fce3eac629b436d:/ext/B/B.xs diff --git a/ext/B/B.xs b/ext/B/B.xs index 1208c2e..a58ff00 100644 --- a/ext/B/B.xs +++ b/ext/B/B.xs @@ -169,11 +169,17 @@ cc_opclass(pTHX_ const OP *o) * Character translations (tr///) are usually a PVOP, keeping a * pointer to a table of shorts used to look up translations. * Under utf8, however, a simple table isn't practical; instead, - * the OP is an SVOP, and the SV is a reference to a swash + * the OP is an SVOP (or, under threads, a PADOP), + * and the SV is a reference to a swash * (i.e., an RV pointing to an HV). */ return (o->op_private & (OPpTRANS_TO_UTF|OPpTRANS_FROM_UTF)) +#if defined(USE_ITHREADS) \ + && (PERL_VERSION > 8 || (PERL_VERSION == 8 && PERL_SUBVERSION >= 9)) + ? OPc_PADOP : OPc_PVOP; +#else ? OPc_SVOP : OPc_PVOP; +#endif case OA_LOOP: return OPc_LOOP; @@ -229,25 +235,22 @@ cc_opclass(pTHX_ const OP *o) return OPc_BASEOP; } -static char * -cc_opclassname(pTHX_ const OP *o) +static SV * +make_op_object(pTHX_ const OP *o) { - return (char *)opclassnames[cc_opclass(aTHX_ o)]; + SV *opsv = sv_newmortal(); + sv_setiv(newSVrv(opsv, opclassnames[cc_opclass(aTHX_ o)]), PTR2IV(o)); + return opsv; } -/* FIXME - figure out how to get the typemap to assign this to ST(0), rather - than creating a new mortal for ST(0) then passing it in as the first - argument. */ static SV * -make_sv_object(pTHX_ SV *arg, SV *sv) +make_sv_object(pTHX_ SV *sv) { + SV *const arg = sv_newmortal(); const char *type = 0; IV iv; dMY_CXT; - if (!arg) - arg = sv_newmortal(); - for (iv = 0; iv < sizeof(specialsv_list)/sizeof(SV*); iv++) { if (sv == specialsv_list[iv]) { type = "B::SPECIAL"; @@ -285,8 +288,9 @@ make_temp_object(pTHX_ SV *temp) } static SV * -make_warnings_object(pTHX_ STRLEN *warnings) +make_warnings_object(pTHX_ const COP *const cop) { + const STRLEN *const warnings = cop->cop_warnings; const char *type = 0; dMY_CXT; IV iv = sizeof(specialsv_list)/sizeof(SV*); @@ -320,10 +324,10 @@ make_cop_io_object(pTHX_ COP *cop) Perl_emulate_cop_io(aTHX_ cop, value); if(SvOK(value)) { - return make_sv_object(aTHX_ NULL, value); + return make_sv_object(aTHX_ value); } else { SvREFCNT_dec(value); - return make_sv_object(aTHX_ NULL, NULL); + return make_sv_object(aTHX_ NULL); } } #endif @@ -471,47 +475,57 @@ cchar(pTHX_ SV *sv) # define PMOP_pmdynflags(o) o->op_pmdynflags #endif -static void -walkoptree(pTHX_ SV *opsv, const char *method) +static SV * +walkoptree(pTHX_ OP *o, const char *method, SV *ref) { dSP; - OP *o, *kid; + OP *kid; + SV *object; + const char *const classname = opclassnames[cc_opclass(aTHX_ o)]; dMY_CXT; - if (!SvROK(opsv)) - croak("opsv is not a reference"); - opsv = sv_mortalcopy(opsv); - o = INT2PTR(OP*,SvIV((SV*)SvRV(opsv))); + /* Check that no-one has changed our reference, or is holding a reference + to it. */ + if (SvREFCNT(ref) == 1 && SvROK(ref) && SvTYPE(ref) == SVt_RV + && (object = SvRV(ref)) && SvREFCNT(object) == 1 + && SvTYPE(object) == SVt_PVMG && SvIOK_only(object) + && !SvMAGICAL(object) && !SvMAGIC(object) && SvSTASH(object)) { + /* Looks good, so rebless it for the class we need: */ + sv_bless(ref, gv_stashpv(classname, GV_ADD)); + } else { + /* Need to make a new one. */ + ref = sv_newmortal(); + object = newSVrv(ref, classname); + } + sv_setiv(object, PTR2IV(o)); + if (walkoptree_debug) { PUSHMARK(sp); - XPUSHs(opsv); + XPUSHs(ref); PUTBACK; perl_call_method("walkoptree_debug", G_DISCARD); } PUSHMARK(sp); - XPUSHs(opsv); + XPUSHs(ref); 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) { - /* Use the same opsv. Rely on methods not to mess it up. */ - sv_setiv(newSVrv(opsv, cc_opclassname(aTHX_ kid)), PTR2IV(kid)); - walkoptree(aTHX_ opsv, method); + ref = walkoptree(aTHX_ kid, method, ref); } } if (o && (cc_opclass(aTHX_ o) == OPc_PMOP) && o->op_type != OP_PUSHRE && (kid = PMOP_pmreplroot(cPMOPo))) { - sv_setiv(newSVrv(opsv, cc_opclassname(aTHX_ kid)), PTR2IV(kid)); - walkoptree(aTHX_ opsv, method); + ref = walkoptree(aTHX_ kid, method, ref); } + return ref; } static SV ** oplist(pTHX_ OP *o, SV **SP) { for(; o; o = o->op_next) { - SV *opsv; #if PERL_VERSION >= 9 if (o->op_opt == 0) break; @@ -521,9 +535,7 @@ oplist(pTHX_ OP *o, SV **SP) break; o->op_seq = 0; #endif - opsv = sv_newmortal(); - sv_setiv(newSVrv(opsv, cc_opclassname(aTHX_ (OP*)o)), PTR2IV(o)); - XPUSHs(opsv); + XPUSHs(make_op_object(aTHX_ o)); switch (o->op_type) { case OP_SUBST: SP = oplist(aTHX_ PMOP_pmreplstart(cPMOPo), SP); @@ -587,9 +599,36 @@ typedef HE *B__HE; typedef struct refcounted_he *B__RHE; #endif +#ifdef USE_ITHREADS +# define ASSIGN_COMMON_ALIAS(var) \ + STMT_START { XSANY.any_i32 = offsetof(struct interpreter, var); } STMT_END +#else +# define ASSIGN_COMMON_ALIAS(var) \ + STMT_START { XSANY.any_ptr = (void *)&PL_##var; } STMT_END +#endif + +/* This needs to be ALIASed in a custom way, hence can't easily be defined as + a regular XSUB. */ +static XSPROTO(intrpvar_sv_common); /* prototype to pass -Wmissing-prototypes */ +static XSPROTO(intrpvar_sv_common) +{ + dVAR; + dXSARGS; + SV *ret; + if (items != 0) + croak_xs_usage(cv, ""); +#ifdef USE_ITHREADS + ret = *(SV **)(XSANY.any_i32 + (char *)my_perl); +#else + ret = *(SV **)(XSANY.any_ptr); +#endif + ST(0) = make_sv_object(aTHX_ ret); + XSRETURN(1); +} + #include "const-c.inc" -MODULE = B PACKAGE = B PREFIX = B_ +MODULE = B PACKAGE = B INCLUDE: const-xs.inc @@ -597,8 +636,8 @@ PROTOTYPES: DISABLE BOOT: { - HV *stash = gv_stashpvs("B", GV_ADD); - AV *export_ok = perl_get_av("B::EXPORT_OK", GV_ADD); + CV *cv; + const char *file = __FILE__; MY_CXT_INIT; specialsv_list[0] = Nullsv; specialsv_list[1] = &PL_sv_undef; @@ -607,124 +646,84 @@ BOOT: specialsv_list[4] = (SV *) pWARN_ALL; specialsv_list[5] = (SV *) pWARN_NONE; specialsv_list[6] = (SV *) pWARN_STD; -#if PERL_VERSION <= 8 -# define OPpPAD_STATE 0 -#endif -} - -#define B_main_cv() PL_main_cv -#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 -#define B_comppadlist() (PL_main_cv ? CvPADLIST(PL_main_cv) : CvPADLIST(PL_compcv)) -#define B_sv_undef() &PL_sv_undef -#define B_sv_yes() &PL_sv_yes -#define B_sv_no() &PL_sv_no -#define B_formfeed() PL_formfeed -#ifdef USE_ITHREADS -#define B_regex_padav() PL_regex_padav -#endif - -B::AV -B_init_av() - -B::AV -B_check_av() - + + cv = newXS("B::init_av", intrpvar_sv_common, file); + ASSIGN_COMMON_ALIAS(Iinitav); + cv = newXS("B::check_av", intrpvar_sv_common, file); + ASSIGN_COMMON_ALIAS(Icheckav_save); #if PERL_VERSION >= 9 - -B::AV -B_unitcheck_av() - + cv = newXS("B::unitcheck_av", intrpvar_sv_common, file); + ASSIGN_COMMON_ALIAS(Iunitcheckav_save); #endif - -B::AV -B_begin_av() - -B::AV -B_end_av() - -B::GV -B_inc_gv() - + cv = newXS("B::begin_av", intrpvar_sv_common, file); + ASSIGN_COMMON_ALIAS(Ibeginav_save); + cv = newXS("B::end_av", intrpvar_sv_common, file); + ASSIGN_COMMON_ALIAS(Iendav); + cv = newXS("B::main_cv", intrpvar_sv_common, file); + ASSIGN_COMMON_ALIAS(Imain_cv); + cv = newXS("B::inc_gv", intrpvar_sv_common, file); + ASSIGN_COMMON_ALIAS(Iincgv); + cv = newXS("B::defstash", intrpvar_sv_common, file); + ASSIGN_COMMON_ALIAS(Idefstash); + cv = newXS("B::curstash", intrpvar_sv_common, file); + ASSIGN_COMMON_ALIAS(Icurstash); + cv = newXS("B::formfeed", intrpvar_sv_common, file); + ASSIGN_COMMON_ALIAS(Iformfeed); #ifdef USE_ITHREADS - -B::AV -B_regex_padav() - + cv = newXS("B::regex_padav", intrpvar_sv_common, file); + ASSIGN_COMMON_ALIAS(Iregex_padav); #endif - -B::CV -B_main_cv() - -B::OP -B_main_root() - -B::OP -B_main_start() + cv = newXS("B::warnhook", intrpvar_sv_common, file); + ASSIGN_COMMON_ALIAS(Iwarnhook); + cv = newXS("B::diehook", intrpvar_sv_common, file); + ASSIGN_COMMON_ALIAS(Idiehook); +} long -B_amagic_generation() - -long -B_sub_generation() - -B::AV -B_comppadlist() - -B::SV -B_sv_undef() - -B::SV -B_sv_yes() - -B::SV -B_sv_no() - -B::HV -B_curstash() - -B::HV -B_defstash() - -U8 -B_dowarn() +amagic_generation() + CODE: + RETVAL = PL_amagic_generation; + OUTPUT: + RETVAL -B::SV -B_formfeed() +void +comppadlist() + PPCODE: + PUSHs(make_sv_object(aTHX_ (SV *)(PL_main_cv ? CvPADLIST(PL_main_cv) + : CvPADLIST(PL_compcv)))); void -B_warnhook() - CODE: - ST(0) = make_sv_object(aTHX_ NULL, PL_warnhook); +sv_undef() + ALIAS: + sv_no = 1 + sv_yes = 2 + PPCODE: + PUSHs(make_sv_object(aTHX_ ix > 1 ? &PL_sv_yes + : ix < 1 ? &PL_sv_undef + : &PL_sv_no)); void -B_diehook() - CODE: - ST(0) = make_sv_object(aTHX_ NULL, PL_diehook); +main_root() + ALIAS: + main_start = 1 + PPCODE: + PUSHs(make_op_object(aTHX_ ix ? PL_main_start : PL_main_root)); -MODULE = B PACKAGE = B +UV +sub_generation() + ALIAS: + dowarn = 1 + CODE: + RETVAL = ix ? PL_dowarn : PL_sub_generation; + OUTPUT: + RETVAL void -walkoptree(opsv, method) - SV * opsv +walkoptree(op, method) + B::OP op const char * method CODE: - walkoptree(aTHX_ opsv, method); + (void) walkoptree(aTHX_ op, method, &PL_sv_undef); int walkoptree_debug(...) @@ -742,15 +741,13 @@ IV address(sv) SV * sv -B::SV +void svref_2object(sv) SV * sv - CODE: + PPCODE: if (!SvROK(sv)) croak("argument is not a reference"); - RETVAL = (SV*)SvRV(sv); - OUTPUT: - RETVAL + PUSHs(make_sv_object(aTHX_ SvRV(sv))); void opnumber(name) @@ -800,13 +797,13 @@ cast_I32(i) void minus_c() + ALIAS: + save_BEGINs = 1 CODE: - PL_minus_c = TRUE; - -void -save_BEGINs() - CODE: - PL_savebegin = TRUE; + if (ix) + PL_savebegin = TRUE; + else + PL_minus_c = TRUE; SV * cstring(sv) @@ -831,32 +828,136 @@ threadsv_names() # endif #endif -#define OP_next(o) o->op_next -#define OP_sibling(o) o->op_sibling -#define OP_targ(o) o->op_targ -#define OP_flags(o) o->op_flags -#define OP_private(o) o->op_private +#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 OP_next_ix OPp | offsetof(struct op, op_next) +#define OP_sibling_ix OPp | offsetof(struct op, op_sibling) +#define UNOP_first_ix OPp | offsetof(struct unop, op_first) +#define BINOP_last_ix OPp | offsetof(struct binop, op_last) +#define LOGOP_other_ix OPp | offsetof(struct logop, op_other) +#if PERL_VERSION >= 9 +# define PMOP_pmreplstart_ix \ + OPp | offsetof(struct pmop, op_pmstashstartu.op_pmreplstart) +#else +# define PMOP_pmreplstart_ix OPp | offsetof(struct pmop, op_pmreplstart) +#endif +#define LOOP_redoop_ix OPp | offsetof(struct loop, op_redoop) +#define LOOP_nextop_ix OPp | offsetof(struct loop, op_nextop) +#define LOOP_lastop_ix OPp | offsetof(struct loop, op_lastop) + +#define OP_targ_ix PADOFFSETp | offsetof(struct op, op_targ) +#define OP_flags_ix U8p | offsetof(struct op, op_flags) +#define OP_private_ix U8p | offsetof(struct op, op_private) + +#define PMOP_pmflags_ix U32p | offsetof(struct pmop, op_pmflags) + +#ifdef USE_ITHREADS +#define PMOP_pmoffset_ix IVp | offsetof(struct pmop, op_pmoffset) +#endif + +# Yes, B::SV::sv and B::SV::gv really do end up generating identical code. +#define SVOP_sv_ix SVp | offsetof(struct svop, op_sv) +#define SVOP_gv_ix SVp | offsetof(struct svop, op_sv) + +#define PADOP_padix_ix PADOFFSETp | offsetof(struct padop, op_padix) + +#define COP_seq_ix U32p | offsetof(struct cop, cop_seq) +#define COP_line_ix line_tp | offsetof(struct cop, cop_line) +#if PERL_VERSION >= 9 +#define COP_hints_ix U32p | offsetof(struct cop, cop_hints) +#else +#define COP_hints_ix U8p | offsetof(struct cop, op_private) +#endif + +#ifdef USE_ITHREADS +#define COP_stashpv_ix char_pp | offsetof(struct cop, cop_stashpv) +#define COP_file_ix char_pp | offsetof(struct cop, cop_file) +#else +#define COP_stash_ix SVp | offsetof(struct cop, cop_stash) +#define COP_filegv_ix SVp | offsetof(struct cop, cop_filegv) +#endif -MODULE = B PACKAGE = B::OP PREFIX = OP_ +MODULE = B PACKAGE = B::OP size_t -OP_size(o) +size(o) B::OP o CODE: RETVAL = opsizes[cc_opclass(aTHX_ o)]; OUTPUT: RETVAL -B::OP -OP_next(o) - B::OP o - -B::OP -OP_sibling(o) +# The type checking code in B has always been identical for all OP types, +# irrespective of whether the action is actually defined on that OP. +# We should fix this +void +next(o) B::OP o + ALIAS: + B::OP::next = OP_next_ix + B::OP::sibling = OP_sibling_ix + B::OP::targ = OP_targ_ix + B::OP::flags = OP_flags_ix + B::OP::private = OP_private_ix + B::UNOP::first = UNOP_first_ix + B::BINOP::last = BINOP_last_ix + B::LOGOP::other = LOGOP_other_ix + B::PMOP::pmreplstart = PMOP_pmreplstart_ix + B::LOOP::redoop = LOOP_redoop_ix + B::LOOP::nextop = LOOP_nextop_ix + B::LOOP::lastop = LOOP_lastop_ix + B::PMOP::pmflags = PMOP_pmflags_ix + B::SVOP::sv = SVOP_sv_ix + B::SVOP::gv = SVOP_gv_ix + B::PADOP::padix = PADOP_padix_ix + B::COP::cop_seq = COP_seq_ix + B::COP::line = COP_line_ix + B::COP::hints = COP_hints_ix + PREINIT: + char *ptr; + SV *ret; + PPCODE: + ptr = (ix & 0xFFFF) + (char *)o; + switch ((U8)(ix >> 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; +#ifdef USE_ITHREADS + case (U8)(IVp >> 16): + ret = sv_2mortal(newSViv(*((IV*)ptr))); + break; + case (U8)(char_pp >> 16): + ret = sv_2mortal(newSVpv(*((char **)ptr), 0)); + break; +#endif + } + ST(0) = ret; + XSRETURN(1); char * -OP_name(o) +name(o) B::OP o ALIAS: desc = 1 @@ -866,7 +967,7 @@ OP_name(o) RETVAL void -OP_ppaddr(o) +ppaddr(o) B::OP o PREINIT: int i; @@ -878,14 +979,10 @@ OP_ppaddr(o) sv_catpvs(sv, "]"); ST(0) = sv; -PADOFFSET -OP_targ(o) - B::OP o - #if PERL_VERSION >= 9 # These 3 are all bitfields, so we can't take their addresses. UV -OP_type(o) +type(o) B::OP o ALIAS: opt = 1 @@ -907,7 +1004,7 @@ OP_type(o) #else UV -OP_type(o) +type(o) B::OP o ALIAS: seq = 1 @@ -924,48 +1021,16 @@ OP_type(o) #endif -U8 -OP_flags(o) - B::OP o - -U8 -OP_private(o) - B::OP o - void -OP_oplist(o) +oplist(o) B::OP o PPCODE: SP = oplist(aTHX_ o, SP); -#define UNOP_first(o) o->op_first - -MODULE = B PACKAGE = B::UNOP PREFIX = UNOP_ - -B::OP -UNOP_first(o) - B::UNOP o - -#define BINOP_last(o) o->op_last - -MODULE = B PACKAGE = B::BINOP PREFIX = BINOP_ - -B::OP -BINOP_last(o) - B::BINOP o - -#define LOGOP_other(o) o->op_other - -MODULE = B PACKAGE = B::LOGOP PREFIX = LOGOP_ - -B::OP -LOGOP_other(o) - B::LOGOP o - -MODULE = B PACKAGE = B::LISTOP PREFIX = LISTOP_ +MODULE = B PACKAGE = B::LISTOP U32 -LISTOP_children(o) +children(o) B::LISTOP o OP * kid = NO_INIT int i = NO_INIT @@ -975,15 +1040,7 @@ LISTOP_children(o) i++; RETVAL = i; OUTPUT: - RETVAL - -#ifdef USE_ITHREADS -#define PMOP_pmoffset(o) o->op_pmoffset -#define PMOP_pmstashpv(o) PmopSTASHPV(o); -#else -#define PMOP_pmstash(o) PmopSTASH(o); -#endif -#define PMOP_pmflags(o) o->op_pmflags + RETVAL MODULE = B PACKAGE = B::PMOP PREFIX = PMOP_ @@ -994,10 +1051,10 @@ PMOP_pmreplroot(o) B::PMOP o OP * root = NO_INIT CODE: - ST(0) = sv_newmortal(); root = o->op_pmreplroot; /* OP_PUSHRE stores an SV* instead of an OP* in op_pmreplroot */ if (o->op_type == OP_PUSHRE) { + ST(0) = sv_newmortal(); # ifdef USE_ITHREADS sv_setiv(ST(0), INT2PTR(PADOFFSET,root) ); # else @@ -1007,7 +1064,7 @@ PMOP_pmreplroot(o) # endif } else { - sv_setiv(newSVrv(ST(0), cc_opclassname(aTHX_ root)), PTR2IV(root)); + ST(0) = make_op_object(aTHX_ root); } #else @@ -1016,12 +1073,13 @@ void PMOP_pmreplroot(o) B::PMOP o CODE: - ST(0) = sv_newmortal(); if (o->op_type == OP_PUSHRE) { # ifdef USE_ITHREADS + ST(0) = sv_newmortal(); sv_setiv(ST(0), o->op_pmreplrootu.op_pmtargetoff); # else GV *const target = o->op_pmreplrootu.op_pmtargetgv; + ST(0) = sv_newmortal(); sv_setiv(newSVrv(ST(0), target ? svclassnames[SvTYPE((SV*)target)] : "B::SV"), PTR2IV(target)); @@ -1029,30 +1087,13 @@ PMOP_pmreplroot(o) } else { OP *const root = o->op_pmreplrootu.op_pmreplroot; - sv_setiv(newSVrv(ST(0), cc_opclassname(aTHX_ root)), - PTR2IV(root)); + ST(0) = make_op_object(aTHX_ root); } #endif -B::OP -PMOP_pmreplstart(o) - B::PMOP o - -#if PERL_VERSION < 9 -#define PMOP_pmnext(o) o->op_pmnext - -B::PMOP -PMOP_pmnext(o) - B::PMOP o - -#endif - #ifdef USE_ITHREADS - -IV -PMOP_pmoffset(o) - B::PMOP o +#define PMOP_pmstashpv(o) PmopSTASHPV(o); char* PMOP_pmstashpv(o) @@ -1060,18 +1101,22 @@ PMOP_pmstashpv(o) #else -B::HV +void PMOP_pmstash(o) B::PMOP o + PPCODE: + PUSHs(make_sv_object(aTHX_ (SV *) PmopSTASH(o))); #endif -U32 -PMOP_pmflags(o) - B::PMOP o - #if PERL_VERSION < 9 +void +PMOP_pmnext(o) + B::PMOP o + PPCODE: + PUSHs(make_op_object(aTHX_ o->op_pmnext)); + U32 PMOP_pmpermflags(o) B::PMOP o @@ -1085,71 +1130,79 @@ PMOP_pmdynflags(o) void PMOP_precomp(o) B::PMOP o - REGEXP * rx = NO_INIT + PREINIT: + dXSI32; + REGEXP *rx; CODE: - ST(0) = sv_newmortal(); rx = PM_GETRE(o); - if (rx) - sv_setpvn(ST(0), RX_PRECOMP(rx), RX_PRELEN(rx)); - -#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(rx)); - + if (rx) { +#if PERL_VERSION >= 9 + if (ix) { + sv_setuv(ST(0), RX_EXTFLAGS(rx)); + } else #endif + { + sv_setpvn(ST(0), RX_PRECOMP(rx), RX_PRELEN(rx)); + } + } -#define SVOP_sv(o) cSVOPo->op_sv -#define SVOP_gv(o) ((GV*)cSVOPo->op_sv) - -MODULE = B PACKAGE = B::SVOP PREFIX = SVOP_ - -B::SV -SVOP_sv(o) - B::SVOP o - -B::GV -SVOP_gv(o) - B::SVOP o - -#define PADOP_padix(o) o->op_padix -#define PADOP_sv(o) (o->op_padix ? PAD_SVl(o->op_padix) : Nullsv) -#define PADOP_gv(o) ((o->op_padix \ - && SvTYPE(PAD_SVl(o->op_padix)) == SVt_PVGV) \ - ? (GV*)PAD_SVl(o->op_padix) : (GV *)NULL) - -MODULE = B PACKAGE = B::PADOP PREFIX = PADOP_ - -PADOFFSET -PADOP_padix(o) - B::PADOP o +BOOT: +{ + CV *cv; +#ifdef USE_ITHREADS + cv = newXS("B::PMOP::pmoffset", XS_B__OP_next, __FILE__); + XSANY.any_i32 = PMOP_pmoffset_ix; + cv = newXS("B::COP::stashpv", XS_B__OP_next, __FILE__); + XSANY.any_i32 = COP_stashpv_ix; + cv = newXS("B::COP::file", XS_B__OP_next, __FILE__); + XSANY.any_i32 = COP_file_ix; +#else + cv = newXS("B::COP::stash", XS_B__OP_next, __FILE__); + XSANY.any_i32 = COP_stash_ix; + cv = newXS("B::COP::filegv", XS_B__OP_next, __FILE__); + XSANY.any_i32 = COP_filegv_ix; +#endif +#if PERL_VERSION >= 9 + cv = newXS("B::PMOP::reflags", XS_B__PMOP_precomp, __FILE__); + XSANY.any_i32 = 1; +#endif +} -B::SV -PADOP_sv(o) - B::PADOP o +MODULE = B PACKAGE = B::PADOP -B::GV -PADOP_gv(o) +void +sv(o) B::PADOP o + PREINIT: + SV *ret; + ALIAS: + gv = 1 + PPCODE: + /* 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 (o->op_padix) { + ret = PAD_SVl(o->op_padix); + if (ix && SvTYPE(ret) != SVt_PVGV) + ret = NULL; + } else { + ret = NULL; + } + PUSHs(make_sv_object(aTHX_ ret)); -MODULE = B PACKAGE = B::PVOP PREFIX = PVOP_ +MODULE = B PACKAGE = B::PVOP void -PVOP_pv(o) +pv(o) B::PVOP o CODE: /* * OP_TRANS uses op_pv to point to a table of 256 or >=258 shorts * whereas other PVOPs point to a null terminated string. */ - if (o->op_type == OP_TRANS && + if ((o->op_type == OP_TRANS || o->op_type == OP_TRANSR) && (o->op_private & OPpTRANS_COMPLEMENT) && !(o->op_private & OPpTRANS_DELETE)) { @@ -1157,105 +1210,65 @@ PVOP_pv(o) const short entries = 257 + tbl[256]; ST(0) = newSVpvn_flags(o->op_pv, entries * sizeof(short), SVs_TEMP); } - else if (o->op_type == OP_TRANS) { + else if (o->op_type == OP_TRANS || o->op_type == OP_TRANSR) { ST(0) = newSVpvn_flags(o->op_pv, 256 * sizeof(short), SVs_TEMP); } else ST(0) = newSVpvn_flags(o->op_pv, strlen(o->op_pv), SVs_TEMP); -#define LOOP_redoop(o) o->op_redoop -#define LOOP_nextop(o) o->op_nextop -#define LOOP_lastop(o) o->op_lastop - -MODULE = B PACKAGE = B::LOOP PREFIX = LOOP_ - - -B::OP -LOOP_redoop(o) - B::LOOP o - -B::OP -LOOP_nextop(o) - B::LOOP o - -B::OP -LOOP_lastop(o) - B::LOOP o - #define COP_label(o) CopLABEL(o) -#define COP_stashpv(o) CopSTASHPV(o) -#define COP_stash(o) CopSTASH(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) CopARYBASE_get(o) -#define COP_line(o) CopLINE(o) -#define COP_hints(o) CopHINTS_get(o) MODULE = B PACKAGE = B::COP PREFIX = COP_ -#if PERL_VERSION >= 11 - const char * COP_label(o) B::COP o -#else +# Both pairs of accessors are provided for both ithreads and not, but for each, +# one pair is direct structure access, and 1 pair "faked up" with a more complex +# macro. We implement the direct structure access pair using the common code +# above (B::OP::next) + +#ifdef USE_ITHREADS -char * -COP_label(o) +void +COP_stash(o) B::COP o + ALIAS: + filegv = 1 + PPCODE: + PUSHs(make_sv_object(aTHX_ + ix ? (SV *)CopFILEGV(o) : (SV *)CopSTASH(o))); -#endif +#else char * COP_stashpv(o) B::COP o + ALIAS: + file = 1 + CODE: + RETVAL = ix ? CopFILE(o) : CopSTASHPV(o); + OUTPUT: + RETVAL -B::HV -COP_stash(o) - B::COP o - -char * -COP_file(o) - B::COP o - -B::GV -COP_filegv(o) - B::COP o - - -U32 -COP_cop_seq(o) - B::COP o +#endif I32 COP_arybase(o) B::COP o -U32 -COP_line(o) - B::COP o - void COP_warnings(o) B::COP o - PPCODE: -#if PERL_VERSION >= 9 - ST(0) = make_warnings_object(aTHX_ o->cop_warnings); -#else - ST(0) = make_sv_object(aTHX_ NULL, o->cop_warnings); -#endif - XSRETURN(1); - -void -COP_io(o) - B::COP o - PPCODE: + ALIAS: + io = 1 + PPCODE: #if PERL_VERSION >= 9 - ST(0) = make_cop_io_object(aTHX_ o); + ST(0) = ix ? make_cop_io_object(aTHX_ o) : make_warnings_object(aTHX_ o); #else - ST(0) = make_sv_object(aTHX_ NULL, o->cop_io); + ST(0) = make_sv_object(aTHX_ ix ? o->cop_io : o->cop_warnings); #endif XSRETURN(1); @@ -1271,73 +1284,244 @@ COP_hints_hash(o) #endif -U32 -COP_hints(o) - B::COP o - MODULE = B PACKAGE = B::SV +#define MAGICAL_FLAG_BITS (SVs_GMG|SVs_SMG|SVs_RMG) + U32 -SvTYPE(sv) +REFCNT(sv) B::SV sv + ALIAS: + FLAGS = 0xFFFFFFFF + SvTYPE = SVTYPEMASK + POK = SVf_POK + ROK = SVf_ROK + MAGICAL = MAGICAL_FLAG_BITS + CODE: + RETVAL = ix ? (SvFLAGS(sv) & (U32)ix) : SvREFCNT(sv); + OUTPUT: + RETVAL -#define object_2svref(sv) sv -#define SVREF SV * - -SVREF -object_2svref(sv) - B::SV sv - -MODULE = B PACKAGE = B::SV PREFIX = Sv - -U32 -SvREFCNT(sv) +void +object_2svref(sv) B::SV sv + PPCODE: + ST(0) = sv_2mortal(newRV(sv)); + XSRETURN(1); + +MODULE = B PACKAGE = B::IV PREFIX = Sv -U32 -SvFLAGS(sv) - B::SV sv +IV +SvIV(sv) + B::IV sv -U32 -SvPOK(sv) - B::SV sv +MODULE = B PACKAGE = B::IV -U32 -SvROK(sv) - B::SV sv +#define sv_SVp 0x00000 +#define sv_IVp 0x10000 +#define sv_UVp 0x20000 +#define sv_STRLENp 0x30000 +#define sv_U32p 0x40000 +#define sv_U8p 0x50000 +#define sv_char_pp 0x60000 +#define sv_NVp 0x70000 +#define sv_char_p 0x80000 +#define sv_SSize_tp 0x90000 +#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) -U32 -SvMAGICAL(sv) - B::SV sv +#if PERL_VERSION >= 10 +#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) +#else +#define NV_cop_seq_range_low_ix \ + sv_NVp | offsetof(struct xpvnv, xnv_nv) +#define NV_cop_seq_range_high_ix \ + sv_UVp | offsetof(struct xpvnv, xuv_uv) +#define NV_parent_pad_index_ix \ + sv_NVp | offsetof(struct xpvnv, xnv_nv) +#define NV_parent_fakelex_flags_ix \ + sv_UVp | offsetof(struct xpvnv, xuv_uv) +#endif -MODULE = B PACKAGE = B::IV PREFIX = Sv +#define PV_cur_ix sv_STRLENp | offsetof(struct xpv, xpv_cur) +#define PV_len_ix sv_STRLENp | offsetof(struct xpv, xpv_len) -IV -SvIV(sv) - B::IV sv +#define PVMG_stash_ix sv_SVp | offsetof(struct xpvmg, xmg_stash) -IV -SvIVX(sv) - B::IV sv +#if PERL_VERSION >= 10 +#define PVBM_useful_ix sv_I32p | offsetof(struct xpvgv, xiv_u.xivu_i32) +#define PVBM_previous_ix sv_U32p | offsetof(struct xpvgv, xnv_u.xbm_s.xbm_previous) +#define PVBM_rare_ix sv_U8p | offsetof(struct xpvgv, xnv_u.xbm_s.xbm_rare) +#else +#define PVBM_useful_ix sv_I32p | offsetof(struct xpvbm, xbm_useful) +#define PVBM_previous_ix sv_U16p | offsetof(struct xpvbm, xbm_previous) +#define PVBM_rare_ix sv_U8p | offsetof(struct xpvbm, xbm_rare) +#endif -UV -SvUVX(sv) - B::IV sv - +#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) -MODULE = B PACKAGE = B::IV +#if PERL_VERSION >= 10 +#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) +#else +#define PVGV_stash_ix sv_SVp | offsetof(struct xpvgv, xgv_stash) +#define PVGV_flags_ix sv_U8p | offsetof(struct xpvgv, xgv_flags) +#define PVIO_lines_ix sv_IVp | offsetof(struct xpvio, xio_lines) +#endif -#define needs64bits(sv) ((I32)SvIVX(sv) != SvIVX(sv)) +#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 PVFM_lines_ix sv_IVp | offsetof(struct xpvfm, xfm_lines) + +#define PVCV_stash_ix sv_SVp | offsetof(struct xpvcv, xcv_stash) +#define PVCV_gv_ix sv_SVp | offsetof(struct xpvcv, xcv_gv) +#define PVCV_file_ix sv_char_pp | offsetof(struct xpvcv, xcv_file) +#define PVCV_depth_ix sv_I32p | offsetof(struct xpvcv, xcv_depth) +#define PVCV_padlist_ix sv_SVp | offsetof(struct xpvcv, xcv_padlist) +#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_U16p | offsetof(struct xpvcv, xcv_flags) + +#define PVHV_max_ix sv_STRLENp | offsetof(struct xpvhv, xhv_max) + +#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 -int -needs64bits(sv) - B::IV sv +# 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. +# We should fix this +void +IVX(sv) + B::SV sv + ALIAS: + 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::PVLV::TARGOFF = PVLV_targoff_ix + B::PVLV::TARGLEN = PVLV_targlen_ix + B::PVLV::TARG = PVLV_targ_ix + B::PVLV::TYPE = PVLV_type_ix + B::GV::STASH = PVGV_stash_ix + B::GV::GvFLAGS = PVGV_flags_ix + B::BM::USEFUL = PVBM_useful_ix + B::BM::PREVIOUS = PVBM_previous_ix + B::BM::RARE = PVBM_rare_ix + B::IO::LINES = PVIO_lines_ix + B::IO::PAGE = PVIO_page_ix + B::IO::PAGE_LEN = PVIO_page_len_ix + B::IO::LINES_LEFT = PVIO_lines_left_ix + B::IO::TOP_NAME = PVIO_top_name_ix + B::IO::TOP_GV = PVIO_top_gv_ix + B::IO::FMT_NAME = PVIO_fmt_name_ix + B::IO::FMT_GV = PVIO_fmt_gv_ix + B::IO::BOTTOM_NAME = PVIO_bottom_name_ix + B::IO::BOTTOM_GV = PVIO_bottom_gv_ix + B::IO::IoTYPE = PVIO_type_ix + B::IO::IoFLAGS = PVIO_flags_ix + B::AV::MAX = PVAV_max_ix + B::FM::LINES = PVFM_lines_ix + B::CV::STASH = PVCV_stash_ix + B::CV::GV = PVCV_gv_ix + B::CV::FILE = PVCV_file_ix + B::CV::DEPTH = PVCV_depth_ix + B::CV::PADLIST = PVCV_padlist_ix + B::CV::OUTSIDE = PVCV_outside_ix + B::CV::OUTSIDE_SEQ = PVCV_outside_seq_ix + B::CV::CvFLAGS = PVCV_flags_ix + B::HV::MAX = PVHV_max_ix + B::HV::KEYS = PVHV_keys_ix + PREINIT: + char *ptr; + SV *ret; + PPCODE: + ptr = (ix & 0xFFFF) + (char *)SvANY(sv); + switch ((U8)(ix >> 16)) { + case (U8)(sv_SVp >> 16): + ret = make_sv_object(aTHX_ *((SV **)ptr)); + break; + case (U8)(sv_IVp >> 16): + ret = sv_2mortal(newSViv(*((IV *)ptr))); + break; + case (U8)(sv_UVp >> 16): + ret = sv_2mortal(newSVuv(*((UV *)ptr))); + break; + case (U8)(sv_STRLENp >> 16): + ret = sv_2mortal(newSVuv(*((STRLEN *)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; + case (U8)(sv_char_pp >> 16): + ret = sv_2mortal(newSVpv(*((char **)ptr), 0)); + break; + case (U8)(sv_NVp >> 16): + ret = sv_2mortal(newSVnv(*((NV *)ptr))); + break; + case (U8)(sv_char_p >> 16): + ret = newSVpvn_flags((char *)ptr, 1, SVs_TEMP); + break; + case (U8)(sv_SSize_tp >> 16): + ret = sv_2mortal(newSViv(*((SSize_t *)ptr))); + break; + case (U8)(sv_I32p >> 16): + ret = sv_2mortal(newSVuv(*((I32 *)ptr))); + break; + case (U8)(sv_U16p >> 16): + ret = sv_2mortal(newSVuv(*((U16 *)ptr))); + break; + } + ST(0) = ret; + XSRETURN(1); void packiv(sv) B::IV sv + ALIAS: + needs64bits = 1 CODE: - if (sizeof(IV) == 8) { + if (ix) { + ST(0) = boolSV((I32)SvIVX(sv) != SvIVX(sv)); + } else if (sizeof(IV) == 8) { U32 wp[2]; const IV iv = SvIVX(sv); /* @@ -1359,428 +1543,276 @@ packiv(sv) ST(0) = newSVpvn_flags((char *)&w, 4, SVs_TEMP); } - -#if PERL_VERSION >= 11 - -B::SV -RV(sv) - B::IV sv - CODE: - if( SvROK(sv) ) { - RETVAL = SvRV(sv); - } - else { - croak( "argument is not SvROK" ); - } - OUTPUT: - RETVAL - -#endif - MODULE = B PACKAGE = B::NV PREFIX = Sv NV SvNV(sv) B::NV sv -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 - #if PERL_VERSION < 11 MODULE = B PACKAGE = B::RV PREFIX = Sv -B::SV +void SvRV(sv) B::RV sv + PPCODE: + PUSHs(make_sv_object(aTHX_ SvRV(sv))); -#endif +#else -MODULE = B PACKAGE = B::PV PREFIX = Sv +MODULE = B PACKAGE = B::REGEXP -char* -SvPVX(sv) - B::PV sv +void +REGEX(sv) + B::REGEXP sv + ALIAS: + precomp = 1 + PPCODE: + if (ix) { + PUSHs(newSVpvn_flags(RX_PRECOMP(sv), RX_PRELEN(sv), SVs_TEMP)); + } else { + dXSTARG; + /* FIXME - can we code this method more efficiently? */ + PUSHi(PTR2IV(sv)); + } -B::SV -SvRV(sv) +#endif + +MODULE = B PACKAGE = B::PV + +void +RV(sv) B::PV sv - CODE: - if( SvROK(sv) ) { - RETVAL = SvRV(sv); - } - else { + PPCODE: + if (!SvROK(sv)) croak( "argument is not SvROK" ); - } - OUTPUT: - RETVAL + PUSHs(make_sv_object(aTHX_ SvRV(sv))); void -SvPV(sv) +PV(sv) B::PV sv + ALIAS: + PVX = 1 + PVBM = 2 + B::BM::TABLE = 3 + PREINIT: + const char *p; + STRLEN len = 0; + U32 utf8 = 0; CODE: - if( SvPOK(sv) ) { - STRLEN len = SvCUR(sv); - const char *p = SvPVX_const(sv); - /* FIXME - we need a better way for B to identify PVs that are - in the pads as variable names. */ + if (ix == 3) { + p = SvPV(sv, len); + /* Boyer-Moore table is just after string and its safety-margin \0 */ + p += len + PERL_FBM_TABLE_OFFSET; + len = 256; + } else if (ix == 2) { + /* 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. */ + /* Also, the start pointer has always been SvPVX(sv). Surely it + should be SvPVX(sv) + SvCUR(sv)? The code has faithfully been + refactored with this behaviour, since PVBM was added in + 651aa52ea1faa806. */ + p = SvPVX_const(sv); + len = SvCUR(sv) + (SvVALID(sv) ? 256 + PERL_FBM_TABLE_OFFSET : 0); + } else if (ix) { + p = SvPVX(sv); + len = strlen(p); + } else if (SvPOK(sv)) { + len = SvCUR(sv); + p = SvPVX_const(sv); + utf8 = SvUTF8(sv); +#if PERL_VERSION < 10 + /* Before 5.10 (well 931b58fb28fa5ca7), PAD_COMPNAME_GEN was stored + in SvCUR(), which meant we had to attempt this special casing + to avoid tripping up over variable names in the pads. */ if((SvLEN(sv) && len >= SvLEN(sv))) { /* It claims to be longer than the space allocated for it - presuambly it's a variable name in the pad */ len = strlen(p); } - ST(0) = newSVpvn_flags(p, len, SVs_TEMP | SvUTF8(sv)); +#endif } else { /* XXX for backward compatibility, but should fail */ /* croak( "argument is not SvPOK" ); */ - ST(0) = sv_newmortal(); + p = NULL; } + ST(0) = newSVpvn_flags(p, len, SVs_TEMP | utf8); -# 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) = newSVpvn_flags(SvPVX_const(sv), - SvCUR(sv) + (SvVALID(sv) ? 256 + PERL_FBM_TABLE_OFFSET : 0), - SVs_TEMP); - - -STRLEN -SvLEN(sv) - B::PV sv - -STRLEN -SvCUR(sv) - B::PV sv - -MODULE = B PACKAGE = B::PVMG PREFIX = Sv +MODULE = B PACKAGE = B::PVMG void -SvMAGIC(sv) +MAGIC(sv) B::PVMG sv MAGIC * mg = NO_INIT PPCODE: for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) XPUSHs(make_mg_object(aTHX_ mg)); -MODULE = B PACKAGE = B::PVMG - -B::HV -SvSTASH(sv) - B::PVMG sv - -MODULE = B PACKAGE = B::REGEXP - -#if PERL_VERSION >= 11 - -IV -REGEX(sv) - B::REGEXP sv - CODE: - /* FIXME - can we code this method more efficiently? */ - RETVAL = PTR2IV(sv); - OUTPUT: - RETVAL - -SV* -precomp(sv) - B::REGEXP sv - CODE: - RETVAL = newSVpvn( RX_PRECOMP(sv), RX_PRELEN(sv) ); - OUTPUT: - RETVAL - -#endif - -#define MgMOREMAGIC(mg) mg->mg_moremagic -#define MgPRIVATE(mg) mg->mg_private -#define MgTYPE(mg) mg->mg_type -#define MgFLAGS(mg) mg->mg_flags -#define MgOBJ(mg) mg->mg_obj -#define MgLENGTH(mg) mg->mg_len -#define MgREGEX(mg) PTR2IV(mg->mg_obj) - -MODULE = B PACKAGE = B::MAGIC PREFIX = Mg - -B::MAGIC -MgMOREMAGIC(mg) - B::MAGIC mg - CODE: - if( MgMOREMAGIC(mg) ) { - RETVAL = MgMOREMAGIC(mg); - } - else { - XSRETURN_UNDEF; - } - OUTPUT: - RETVAL - -U16 -MgPRIVATE(mg) - B::MAGIC mg - -char -MgTYPE(mg) - B::MAGIC mg - -U8 -MgFLAGS(mg) - B::MAGIC mg - -B::SV -MgOBJ(mg) - B::MAGIC mg - -IV -MgREGEX(mg) - B::MAGIC mg - CODE: - if(mg->mg_type == PERL_MAGIC_qr) { - RETVAL = MgREGEX(mg); - } - else { - croak( "REGEX is only meaningful on r-magic" ); - } - OUTPUT: - RETVAL - -SV* -precomp(mg) - B::MAGIC mg - CODE: - if (mg->mg_type == PERL_MAGIC_qr) { - REGEXP* rx = (REGEXP*)mg->mg_obj; - RETVAL = Nullsv; - if( rx ) - RETVAL = newSVpvn( RX_PRECOMP(rx), RX_PRELEN(rx) ); - } - else { - croak( "precomp is only meaningful on r-magic" ); - } - OUTPUT: - RETVAL +MODULE = B PACKAGE = B::MAGIC -I32 -MgLENGTH(mg) - B::MAGIC mg - void -MgPTR(mg) +MOREMAGIC(mg) B::MAGIC mg - CODE: - if (mg->mg_ptr){ - if (mg->mg_len >= 0){ - ST(0) = newSVpvn_flags(mg->mg_ptr, mg->mg_len, SVs_TEMP); + ALIAS: + PRIVATE = 1 + TYPE = 2 + FLAGS = 3 + LENGTH = 4 + OBJ = 5 + PTR = 6 + REGEX = 7 + precomp = 8 + PPCODE: + switch (ix) { + case 0: + XPUSHs(mg->mg_moremagic ? make_mg_object(aTHX_ mg->mg_moremagic) + : &PL_sv_undef); + break; + case 1: + mPUSHu(mg->mg_private); + break; + case 2: + PUSHs(newSVpvn_flags(&(mg->mg_type), 1, SVs_TEMP)); + break; + case 3: + mPUSHu(mg->mg_flags); + break; + case 4: + mPUSHi(mg->mg_len); + break; + case 5: + PUSHs(make_sv_object(aTHX_ mg->mg_obj)); + break; + case 6: + if (mg->mg_ptr) { + if (mg->mg_len >= 0) { + PUSHs(newSVpvn_flags(mg->mg_ptr, mg->mg_len, SVs_TEMP)); } else if (mg->mg_len == HEf_SVKEY) { - ST(0) = make_sv_object(aTHX_ NULL, (SV*)mg->mg_ptr); + PUSHs(make_sv_object(aTHX_ (SV*)mg->mg_ptr)); } else - ST(0) = sv_newmortal(); - } else - ST(0) = sv_newmortal(); - -MODULE = B PACKAGE = B::PVLV PREFIX = Lv - -U32 -LvTARGOFF(sv) - B::PVLV sv - -U32 -LvTARGLEN(sv) - B::PVLV sv - -char -LvTYPE(sv) - B::PVLV sv - -B::SV -LvTARG(sv) - B::PVLV sv - -MODULE = B PACKAGE = B::BM PREFIX = Bm - -I32 -BmUSEFUL(sv) - B::BM sv - -U32 -BmPREVIOUS(sv) - B::BM sv - -U8 -BmRARE(sv) - B::BM sv - -void -BmTABLE(sv) - B::BM sv - STRLEN len = NO_INIT - char * str = NO_INIT - CODE: - str = SvPV(sv, len); - /* Boyer-Moore table is just after string and its safety-margin \0 */ - ST(0) = newSVpvn_flags(str + len + PERL_FBM_TABLE_OFFSET, 256, SVs_TEMP); + PUSHs(sv_newmortal()); + } else + PUSHs(sv_newmortal()); + break; + case 7: + if(mg->mg_type == PERL_MAGIC_qr) { + mPUSHi(PTR2IV(mg->mg_obj)); + } else { + croak("REGEX is only meaningful on r-magic"); + } + break; + case 8: + if (mg->mg_type == PERL_MAGIC_qr) { + REGEXP *rx = (REGEXP *)mg->mg_obj; + PUSHs(newSVpvn_flags(rx ? RX_PRECOMP(rx) : NULL, + rx ? RX_PRELEN(rx) : 0, SVs_TEMP)); + } else { + croak( "precomp is only meaningful on r-magic" ); + } + break; + } MODULE = B PACKAGE = B::GV PREFIX = Gv void GvNAME(gv) B::GV gv + ALIAS: + FILE = 1 + B::HV::NAME = 2 CODE: #if PERL_VERSION >= 10 - ST(0) = sv_2mortal(newSVhek(GvNAME_HEK(gv))); + ST(0) = sv_2mortal(newSVhek(!ix ? GvNAME_HEK(gv) + : (ix == 1 ? GvFILE_HEK(gv) + : HvNAME_HEK((HV *)gv)))); #else - ST(0) = newSVpvn_flags(GvNAME(gv), GvNAMELEN(gv), SVs_TEMP); + ST(0) = !ix ? newSVpvn_flags(GvNAME(gv), GvNAMELEN(gv), SVs_TEMP) + : sv_2mortal(newSVpv(ix == 1 ? GvFILE(gv) : HvNAME((HV *)gv), 0)) #endif bool is_empty(gv) B::GV gv + ALIAS: + isGV_with_GP = 1 CODE: - RETVAL = GvGP(gv) == Null(GP*); - OUTPUT: - RETVAL - -bool -isGV_with_GP(gv) - B::GV gv - CODE: + if (ix) { #if PERL_VERSION >= 9 - RETVAL = isGV_with_GP(gv) ? TRUE : FALSE; + RETVAL = isGV_with_GP(gv) ? TRUE : FALSE; #else - RETVAL = TRUE; /* In 5.8 and earlier they all are. */ + RETVAL = TRUE; /* In 5.8 and earlier they all are. */ #endif + } else { + RETVAL = GvGP(gv) == Null(GP*); + } OUTPUT: - RETVAL + RETVAL void* GvGP(gv) B::GV gv -B::HV -GvSTASH(gv) - B::GV gv - -B::SV -GvSV(gv) - B::GV gv - -B::IO -GvIO(gv) - B::GV gv - -B::FM -GvFORM(gv) - B::GV gv - CODE: - RETVAL = (SV*)GvFORM(gv); - OUTPUT: - RETVAL - -B::AV -GvAV(gv) - B::GV gv - -B::HV -GvHV(gv) - B::GV gv - -B::GV -GvEGV(gv) - B::GV gv - -B::CV -GvCV(gv) - B::GV gv - -U32 -GvCVGEN(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) -U32 -GvLINE(gv) - B::GV gv - -char * -GvFILE(gv) - B::GV gv - -B::GV -GvFILEGV(gv) - B::GV gv - -MODULE = B PACKAGE = B::GV - -U32 -GvREFCNT(gv) +void +SV(gv) B::GV gv + ALIAS: + SV = GP_sv_ix + IO = GP_io_ix + CV = GP_cv_ix + CVGEN = GP_cvgen_ix + GvREFCNT = GP_refcnt_ix + HV = GP_hv_ix + AV = GP_av_ix + FORM = GP_form_ix + EGV = GP_egv_ix + LINE = GP_line_ix + PREINIT: + GP *gp; + char *ptr; + SV *ret; + PPCODE: + gp = GvGP(gv); + if (!gp) { + const GV *const gv = CvGV(cv); + Perl_croak(aTHX_ "NULL gp in B::GV::%s", gv ? GvNAME(gv) : "???"); + } + ptr = (ix & 0xFFFF) + (char *)gp; + switch ((U8)(ix >> 16)) { + case (U8)(SVp >> 16): + ret = make_sv_object(aTHX_ *((SV **)ptr)); + break; + case (U8)(U32p >> 16): + ret = sv_2mortal(newSVuv(*((U32*)ptr))); + break; + case (U8)(line_tp >> 16): + ret = sv_2mortal(newSVuv(*((line_t *)ptr))); + break; + } + ST(0) = ret; + XSRETURN(1); -U8 -GvFLAGS(gv) +void +FILEGV(gv) B::GV gv + PPCODE: + PUSHs(make_sv_object(aTHX_ (SV *)GvFILEGV(gv))); MODULE = B PACKAGE = B::IO PREFIX = Io -long -IoLINES(io) - B::IO io - -long -IoPAGE(io) - B::IO io - -long -IoPAGE_LEN(io) - B::IO io - -long -IoLINES_LEFT(io) - B::IO io - -char * -IoTOP_NAME(io) - B::IO io - -B::GV -IoTOP_GV(io) - B::IO io - -char * -IoFMT_NAME(io) - B::IO io - -B::GV -IoFMT_GV(io) - B::IO io - -char * -IoBOTTOM_NAME(io) - B::IO io - -B::GV -IoBOTTOM_GV(io) - B::IO io - #if PERL_VERSION <= 8 short @@ -1812,37 +1844,12 @@ IsSTD(io,name) OUTPUT: RETVAL -MODULE = B PACKAGE = B::IO - -char -IoTYPE(io) - B::IO io - -U8 -IoFLAGS(io) - B::IO io - MODULE = B PACKAGE = B::AV PREFIX = Av SSize_t AvFILL(av) B::AV av -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 @@ -1851,7 +1858,7 @@ AvARRAY(av) SV **svp = AvARRAY(av); I32 i; for (i = 0; i <= AvFILL(av); i++) - XPUSHs(make_sv_object(aTHX_ NULL, svp[i])); + XPUSHs(make_sv_object(aTHX_ svp[i])); } void @@ -1860,12 +1867,18 @@ AvARRAYelt(av, idx) int idx PPCODE: if (idx >= 0 && AvFILL(av) >= 0 && idx <= AvFILL(av)) - XPUSHs(make_sv_object(aTHX_ NULL, (AvARRAY(av)[idx]))); + XPUSHs(make_sv_object(aTHX_ (AvARRAY(av)[idx]))); else - XPUSHs(make_sv_object(aTHX_ NULL, NULL)); + XPUSHs(make_sv_object(aTHX_ NULL)); #if PERL_VERSION < 9 +#define AvOFF(av) ((XPVAV*)SvANY(av))->xof_off + +IV +AvOFF(av) + B::AV av + MODULE = B PACKAGE = B::AV U8 @@ -1874,83 +1887,39 @@ AvFLAGS(av) #endif -MODULE = B PACKAGE = B::FM PREFIX = Fm - -IV -FmLINES(form) - B::FM form - MODULE = B PACKAGE = B::CV PREFIX = Cv U32 CvCONST(cv) B::CV cv -B::HV -CvSTASH(cv) - B::CV cv - -B::OP +void CvSTART(cv) B::CV cv ALIAS: ROOT = 1 - CODE: - RETVAL = CvISXSUB(cv) ? NULL : ix ? CvROOT(cv) : CvSTART(cv); - OUTPUT: - RETVAL - -B::GV -CvGV(cv) - B::CV cv - -char * -CvFILE(cv) - B::CV cv - -long -CvDEPTH(cv) - B::CV cv - -B::AV -CvPADLIST(cv) - B::CV cv - -B::CV -CvOUTSIDE(cv) - B::CV cv - -U32 -CvOUTSIDE_SEQ(cv) - B::CV cv + PPCODE: + PUSHs(make_op_object(aTHX_ CvISXSUB(cv) ? NULL + : ix ? CvROOT(cv) : CvSTART(cv))); void CvXSUB(cv) B::CV cv + ALIAS: + XSUBANY = 1 CODE: - ST(0) = sv_2mortal(newSViv(CvISXSUB(cv) ? PTR2IV(CvXSUB(cv)) : 0)); - + ST(0) = ix && CvCONST(cv) + ? make_sv_object(aTHX_ (SV *)CvXSUBANY(cv).any_ptr) + : sv_2mortal(newSViv(CvISXSUB(cv) + ? (ix ? CvXSUBANY(cv).any_iv + : PTR2IV(CvXSUB(cv))) + : 0)); void -CvXSUBANY(cv) +const_sv(cv) B::CV cv - CODE: - ST(0) = CvCONST(cv) - ? make_sv_object(aTHX_ NULL, (SV *)CvXSUBANY(cv).any_ptr) - : sv_2mortal(newSViv(CvISXSUB(cv) ? CvXSUBANY(cv).any_iv : 0)); - -MODULE = B PACKAGE = B::CV - -U16 -CvFLAGS(cv) - B::CV cv - -MODULE = B PACKAGE = B::CV PREFIX = cv_ - -B::SV -cv_const_sv(cv) - B::CV cv - + PPCODE: + PUSHs(make_sv_object(aTHX_ (SV *)cv_const_sv(cv))); MODULE = B PACKAGE = B::HV PREFIX = Hv @@ -1958,27 +1927,17 @@ STRLEN HvFILL(hv) B::HV hv -STRLEN -HvMAX(hv) - B::HV hv - -I32 -HvKEYS(hv) - B::HV hv - I32 HvRITER(hv) B::HV hv -char * -HvNAME(hv) - B::HV hv - #if PERL_VERSION < 9 B::PMOP HvPMROOT(hv) B::HV hv + PPCODE: + PUSHs(make_op_object(aTHX_ HvPMROOT(hv))); #endif @@ -1994,30 +1953,30 @@ HvARRAY(hv) EXTEND(sp, HvKEYS(hv) * 2); while ((sv = hv_iternextsv(hv, &key, &len))) { mPUSHp(key, len); - PUSHs(make_sv_object(aTHX_ NULL, sv)); + PUSHs(make_sv_object(aTHX_ sv)); } } MODULE = B PACKAGE = B::HE PREFIX = He -B::SV +void HeVAL(he) B::HE he + ALIAS: + SVKEY_force = 1 + PPCODE: + PUSHs(make_sv_object(aTHX_ ix ? HeSVKEY_force(he) : HeVAL(he))); U32 HeHASH(he) B::HE he -B::SV -HeSVKEY_force(he) - B::HE he - -MODULE = B PACKAGE = B::RHE PREFIX = RHE_ +MODULE = B PACKAGE = B::RHE #if PERL_VERSION >= 9 SV* -RHE_HASH(h) +HASH(h) B::RHE h CODE: RETVAL = newRV( (SV*)cophh_2hv(h, 0) );