X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=ext%2FB%2FB.xs;h=b2627aae845780685a4e2c7e68d317b346225037;hb=38d458223cba6a811392b6c55c78b12d7fae269e;hp=63f5a99fa3c21fc976df95136ba0fffc32d19fd3;hpb=f5ba13079587260a0b8a2a6958a44e80adc29fe2;p=p5sagit%2Fp5-mst-13.2.git diff --git a/ext/B/B.xs b/ext/B/B.xs index 63f5a99..b2627aa 100644 --- a/ext/B/B.xs +++ b/ext/B/B.xs @@ -19,7 +19,7 @@ typedef FILE * InputStream; #endif -static char *svclassnames[] = { +static const char* const svclassnames[] = { "B::NULL", "B::IV", "B::NV", @@ -58,7 +58,7 @@ typedef enum { OPc_COP /* 11 */ } opclass; -static char *opclassnames[] = { +static const char* const opclassnames[] = { "B::NULL", "B::OP", "B::UNOP", @@ -73,7 +73,7 @@ static char *opclassnames[] = { "B::COP" }; -static size_t opsizes[] = { +static const size_t opsizes[] = { 0, sizeof(OP), sizeof(UNOP), @@ -101,7 +101,7 @@ START_MY_CXT #define specialsv_list (MY_CXT.x_specialsv_list) static opclass -cc_opclass(pTHX_ OP *o) +cc_opclass(pTHX_ const OP *o) { if (!o) return OPc_NULL; @@ -112,9 +112,20 @@ cc_opclass(pTHX_ 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 @@ -209,15 +220,15 @@ cc_opclass(pTHX_ OP *o) } static char * -cc_opclassname(pTHX_ OP *o) +cc_opclassname(pTHX_ const OP *o) { - return opclassnames[cc_opclass(aTHX_ o)]; + return (char *)opclassnames[cc_opclass(aTHX_ o)]; } static SV * make_sv_object(pTHX_ SV *arg, SV *sv) { - char *type = 0; + const char *type = 0; IV iv; dMY_CXT; @@ -236,6 +247,73 @@ make_sv_object(pTHX_ SV *arg, SV *sv) } 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) +{ + if (CopHINTS_get(cop) & HINT_LEXICAL_IO) { + /* I feel you should be able to simply SvREFCNT_inc the return value + from this, but if you do (and restore the line + my $ioix = $cop->io->ix; + in B::COP::bsave in Bytecode.pm, then you get errors about + "attempt to free temp prematurely ... during global destruction. + The SV's flags are consistent with the error, but quite how the + temp escaped from the save stack is not clear. */ + SV *value = Perl_refcounted_he_fetch(aTHX_ cop->cop_hints_hash, + 0, "open", 4, 0, 0); + return make_temp_object(aTHX_ arg, newSVsv(value)); + } else { + return make_sv_object(aTHX_ arg, NULL); + } +} + +static SV * make_mg_object(pTHX_ SV *arg, MAGIC *mg) { sv_setiv(newSVrv(arg, "B::MAGIC"), PTR2IV(mg)); @@ -246,32 +324,28 @@ static SV * cstring(pTHX_ SV *sv, bool perlstyle) { SV *sstr = newSVpvn("", 0); - STRLEN len; - char *s; - char escbuff[5]; /* to fit backslash, 3 octals + trailing \0 */ if (!SvOK(sv)) sv_setpvn(sstr, "0", 1); - else if (perlstyle && SvUTF8(sv)) - { + else if (perlstyle && SvUTF8(sv)) { SV *tmpsv = sv_newmortal(); /* Temporary SV to feed sv_uni_display */ - len = SvCUR(sv); - s = sv_uni_display(tmpsv, sv, 8*len, UNI_DISPLAY_QQ); - sv_setpv(sstr,"\""); + const STRLEN len = SvCUR(sv); + const char *s = sv_uni_display(tmpsv, sv, 8*len, UNI_DISPLAY_QQ); + sv_setpvn(sstr,"\"",1); while (*s) { if (*s == '"') - sv_catpv(sstr, "\\\""); + sv_catpvn(sstr, "\\\"", 2); else if (*s == '$') - sv_catpv(sstr, "\\$"); + sv_catpvn(sstr, "\\$", 2); else if (*s == '@') - sv_catpv(sstr, "\\@"); + sv_catpvn(sstr, "\\@", 2); else if (*s == '\\') { if (strchr("nrftax\\",*(s+1))) sv_catpvn(sstr, s++, 2); else - sv_catpv(sstr, "\\\\"); + sv_catpvn(sstr, "\\\\", 2); } else /* should always be printable */ sv_catpvn(sstr, s, 1); @@ -283,7 +357,8 @@ cstring(pTHX_ SV *sv, bool perlstyle) else { /* XXX Optimise? */ - s = SvPV(sv, len); + STRLEN len; + const char *s = SvPV(sv, len); sv_catpv(sstr, "\""); for (; len; len--, s++) { @@ -293,8 +368,8 @@ cstring(pTHX_ SV *sv, bool perlstyle) else if (*s == '\\') sv_catpv(sstr, "\\\\"); /* trigraphs - bleagh */ - else if (!perlstyle && *s == '?' && len>=3 && s[1] == '?') - { + else if (!perlstyle && *s == '?' && len>=3 && s[1] == '?') { + char escbuff[5]; /* to fit backslash, 3 octals + trailing \0 */ sprintf(escbuff, "\\%03o", '?'); sv_catpv(sstr, escbuff); } @@ -325,7 +400,8 @@ cstring(pTHX_ SV *sv, bool perlstyle) else { /* Don't want promotion of a signed -1 char in sprintf args */ - unsigned char c = (unsigned char) *s; + char escbuff[5]; /* to fit backslash, 3 octals + trailing \0 */ + const unsigned char c = (unsigned char) *s; sprintf(escbuff, "\\%03o", c); sv_catpv(sstr, escbuff); } @@ -340,13 +416,12 @@ static SV * cchar(pTHX_ SV *sv) { SV *sstr = newSVpvn("'", 1); - STRLEN n_a; - char *s = SvPV(sv, n_a); + const char *s = SvPV_nolen(sv); if (*s == '\'') - sv_catpv(sstr, "\\'"); + sv_catpvn(sstr, "\\'", 2); else if (*s == '\\') - sv_catpv(sstr, "\\\\"); + sv_catpvn(sstr, "\\\\", 2); #ifdef EBCDIC else if (isPRINT(*s)) #else @@ -354,19 +429,19 @@ cchar(pTHX_ SV *sv) #endif /* EBCDIC */ sv_catpvn(sstr, s, 1); else if (*s == '\n') - sv_catpv(sstr, "\\n"); + sv_catpvn(sstr, "\\n", 2); else if (*s == '\r') - sv_catpv(sstr, "\\r"); + sv_catpvn(sstr, "\\r", 2); else if (*s == '\t') - sv_catpv(sstr, "\\t"); + sv_catpvn(sstr, "\\t", 2); else if (*s == '\a') - sv_catpv(sstr, "\\a"); + sv_catpvn(sstr, "\\a", 2); else if (*s == '\b') - sv_catpv(sstr, "\\b"); + sv_catpvn(sstr, "\\b", 2); else if (*s == '\f') - sv_catpv(sstr, "\\f"); + sv_catpvn(sstr, "\\f", 2); else if (*s == '\v') - sv_catpv(sstr, "\\v"); + sv_catpvn(sstr, "\\v", 2); else { /* no trigraph support */ @@ -376,12 +451,12 @@ cchar(pTHX_ SV *sv) sprintf(escbuff, "\\%03o", c); sv_catpv(sstr, escbuff); } - sv_catpv(sstr, "'"); + sv_catpvn(sstr, "'", 1); return sstr; } -void -walkoptree(pTHX_ SV *opsv, char *method) +static void +walkoptree(pTHX_ SV *opsv, const char *method) { dSP; OP *o, *kid; @@ -408,15 +483,15 @@ walkoptree(pTHX_ SV *opsv, char *method) walkoptree(aTHX_ opsv, method); } } - if (o && (cc_opclass(aTHX_ o) == OPc_PMOP) + if (o && (cc_opclass(aTHX_ o) == OPc_PMOP) && o->op_type != OP_PUSHRE && (kid = cPMOPo->op_pmreplroot)) { - sv_setiv(newSVrv(opsv, opclassnames[OPc_PMOP]), PTR2IV(kid)); + sv_setiv(newSVrv(opsv, cc_opclassname(aTHX_ kid)), PTR2IV(kid)); walkoptree(aTHX_ opsv, method); } } -SV ** +static SV ** oplist(pTHX_ OP *o, SV **SP) { for(; o; o = o->op_next) { @@ -488,6 +563,8 @@ typedef GV *B__GV; typedef IO *B__IO; typedef MAGIC *B__MAGIC; +typedef HE *B__HE; +typedef struct refcounted_he *B__RHE; MODULE = B PACKAGE = B PREFIX = B_ @@ -502,9 +579,9 @@ BOOT: 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 #endif @@ -515,11 +592,13 @@ BOOT: #define B_init_av() PL_initav #define B_inc_gv() PL_incgv #define B_check_av() PL_checkav_save +#define B_unitcheck_av() PL_unitcheckav_save #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 @@ -539,6 +618,9 @@ B::AV B_check_av() B::AV +B_unitcheck_av() + +B::AV B_begin_av() B::AV @@ -566,6 +648,9 @@ B_main_start() long B_amagic_generation() +long +B_sub_generation() + B::AV B_comppadlist() @@ -605,7 +690,7 @@ MODULE = B PACKAGE = B void walkoptree(opsv, method) SV * opsv - char * method + const char * method CODE: walkoptree(aTHX_ opsv, method); @@ -637,7 +722,7 @@ svref_2object(sv) void opnumber(name) -char * name +const char * name CODE: { int i; @@ -670,11 +755,10 @@ void hash(sv) SV * sv CODE: - char *s; STRLEN len; U32 hash = 0; char hexhash[19]; /* must fit "0xffffffffffffffff" plus trailing \0 */ - s = SvPV(sv, len); + const char *s = SvPV(sv, len); PERL_HASH(hash, s, len); sprintf(hexhash, "0x%"UVxf, (UV)hash); ST(0) = sv_2mortal(newSVpv(hexhash, 0)); @@ -724,7 +808,7 @@ threadsv_names() #if PERL_VERSION <= 8 # ifdef USE_5005THREADS int i; - STRLEN len = strlen(PL_threadsv_names); + const STRLEN len = strlen(PL_threadsv_names); EXTEND(sp, len); for (i = 0; i < len; i++) @@ -734,7 +818,7 @@ threadsv_names() #define OP_next(o) o->op_next #define OP_sibling(o) o->op_sibling -#define OP_desc(o) PL_op_desc[o->op_type] +#define OP_desc(o) (char *)PL_op_desc[o->op_type] #define OP_targ(o) o->op_targ #define OP_type(o) o->op_type #if PERL_VERSION >= 9 @@ -769,7 +853,7 @@ char * OP_name(o) B::OP o CODE: - RETVAL = PL_op_name[o->op_type]; + RETVAL = (char *)PL_op_name[o->op_type]; OUTPUT: RETVAL @@ -1011,8 +1095,8 @@ PVOP_pv(o) (o->op_private & OPpTRANS_COMPLEMENT) && !(o->op_private & OPpTRANS_DELETE)) { - short* tbl = (short*)o->op_pv; - short entries = 257 + tbl[256]; + const short* const tbl = (short*)o->op_pv; + const short entries = 257 + tbl[256]; ST(0) = sv_2mortal(newSVpv(o->op_pv, entries * sizeof(short))); } else if (o->op_type == OP_TRANS) { @@ -1046,10 +1130,9 @@ 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) MODULE = B PACKAGE = B::COP PREFIX = COP_ @@ -1086,13 +1169,31 @@ U32 COP_line(o) B::COP o -B::SV +void COP_warnings(o) B::COP o + PPCODE: + ST(0) = make_warnings_object(aTHX_ sv_newmortal(), o->cop_warnings); + XSRETURN(1); -B::SV +void COP_io(o) B::COP o + PPCODE: + ST(0) = make_cop_io_object(aTHX_ sv_newmortal(), o); + XSRETURN(1); + +U32 +COP_hints(o) + B::COP o + +B::RHE +COP_hints_hash(o) + B::COP o + CODE: + RETVAL = o->cop_hints_hash; + OUTPUT: + RETVAL MODULE = B PACKAGE = B::SV @@ -1158,7 +1259,7 @@ packiv(sv) CODE: if (sizeof(IV) == 8) { U32 wp[2]; - IV iv = SvIVX(sv); + const IV iv = SvIVX(sv); /* * The following way of spelling 32 is to stop compilers on * 32-bit architectures from moaning about the shift count @@ -1218,8 +1319,16 @@ SvPV(sv) B::PV sv CODE: ST(0) = sv_newmortal(); - if( SvPOK(sv) ) { - sv_setpvn(ST(0), SvPVX(sv), SvCUR(sv)); + if( SvPOK(sv) ) { + /* FIXME - we need a better way for B to identify PVs that are + in the pads as variable names. */ + if((SvLEN(sv) && SvCUR(sv) >= SvLEN(sv))) { + /* It claims to be longer than the space allocated for it - + presuambly it's a variable name in the pad */ + sv_setpv(ST(0), SvPV_nolen_const(sv)); + } else { + sv_setpvn(ST(0), SvPVX_const(sv), SvCUR(sv)); + } SvFLAGS(ST(0)) |= SvUTF8(sv); } else { @@ -1233,7 +1342,7 @@ SvPVBM(sv) B::PV sv CODE: ST(0) = sv_newmortal(); - sv_setpvn(ST(0), SvPVX(sv), + sv_setpvn(ST(0), SvPVX_const(sv), SvCUR(sv) + (SvTYPE(sv) == SVt_PVBM ? 257 : 0)); @@ -1304,7 +1413,7 @@ IV MgREGEX(mg) B::MAGIC mg CODE: - if( mg->mg_type == 'r' ) { + if(mg->mg_type == PERL_MAGIC_qr) { RETVAL = MgREGEX(mg); } else { @@ -1317,8 +1426,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 ); } @@ -1519,7 +1629,7 @@ IoSUBPROCESS(io) bool IsSTD(io,name) B::IO io - char* name + const char* name PREINIT: PerlIO* handle = 0; CODE: @@ -1559,12 +1669,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 @@ -1586,6 +1701,7 @@ AvARRAYelt(av, idx) else XPUSHs(make_sv_object(aTHX_ sv_newmortal(), NULL)); +#if PERL_VERSION < 9 MODULE = B PACKAGE = B::AV @@ -1593,6 +1709,8 @@ U8 AvFLAGS(av) B::AV av +#endif + MODULE = B PACKAGE = B::FM PREFIX = Fm IV @@ -1612,10 +1730,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) @@ -1645,7 +1771,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 @@ -1653,8 +1779,8 @@ CvXSUBANY(cv) B::CV cv CODE: ST(0) = CvCONST(cv) ? - make_sv_object(aTHX_ sv_newmortal(),CvXSUBANY(cv).any_ptr) : - sv_2mortal(newSViv(CvXSUBANY(cv).any_iv)); + make_sv_object(aTHX_ sv_newmortal(),(SV *)CvXSUBANY(cv).any_ptr) : + sv_2mortal(newSViv(CvISXSUB(cv) ? CvXSUBANY(cv).any_iv : 0)); MODULE = B PACKAGE = B::CV @@ -1691,10 +1817,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 @@ -1710,3 +1840,27 @@ 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_ + +SV* +RHE_HASH(h) + B::RHE h + CODE: + RETVAL = newRV( (SV*)Perl_refcounted_he_chain_2hv(aTHX_ h) ); + OUTPUT: + RETVAL