X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=universal.c;h=b082da67ffe0234b5534819843f612e26482cb11;hb=83437becac3a89db6e4fbc7e9b794e0d2e203eca;hp=830e2066ac9135b0d1fb48b58a69261f35482eee;hpb=6d4a7be2b18d1674acf2ccc0da715a204e2d1ed0;p=p5sagit%2Fp5-mst-13.2.git diff --git a/universal.c b/universal.c index 830e206..b082da6 100644 --- a/universal.c +++ b/universal.c @@ -74,11 +74,44 @@ int level; return &sv_no; } +bool +sv_derived_from(sv, name) +SV * sv ; +char * name ; +{ + SV *rv; + char *type; + HV *stash; + + stash = Nullhv; + type = Nullch; + + if (SvGMAGICAL(sv)) + mg_get(sv) ; + + if (SvROK(sv)) { + sv = SvRV(sv); + type = sv_reftype(sv,0); + if(SvOBJECT(sv)) + stash = SvSTASH(sv); + } + else { + stash = gv_stashsv(sv, FALSE); + } + + return (type && strEQ(type,name)) || + (stash && isa_lookup(stash, name, strlen(name), 0) == &sv_yes) + ? TRUE + : FALSE ; + +} + + static XS(XS_UNIVERSAL_isa) { dXSARGS; - SV *sv, *rv; + SV *sv; char *name; if (items != 2) @@ -87,39 +120,7 @@ XS(XS_UNIVERSAL_isa) sv = ST(0); name = (char *)SvPV(ST(1),na); - if (!SvROK(sv)) { - rv = &sv_no; - } - else if((sv = (SV*)SvRV(sv)) && SvOBJECT(sv) && - &sv_yes == isa_lookup(SvSTASH(sv), name, strlen(name), 0)) { - rv = &sv_yes; - } - else { - char *s; - - switch (SvTYPE(sv)) { - case SVt_NULL: - case SVt_IV: - case SVt_NV: - case SVt_RV: - case SVt_PV: - case SVt_PVIV: - case SVt_PVNV: - case SVt_PVBM: - case SVt_PVMG: s = "SCALAR"; break; - case SVt_PVLV: s = "LVALUE"; break; - case SVt_PVAV: s = "ARRAY"; break; - case SVt_PVHV: s = "HASH"; break; - case SVt_PVCV: s = "CODE"; break; - case SVt_PVGV: s = "GLOB"; break; - case SVt_PVFM: s = "FORMATLINE"; break; - case SVt_PVIO: s = "FILEHANDLE"; break; - default: s = "UNKNOWN"; break; - } - rv = strEQ(s,name) ? &sv_yes : &sv_no; - } - - ST(0) = rv; + ST(0) = boolSV(sv_derived_from(sv, name)); XSRETURN(1); } @@ -130,8 +131,7 @@ XS(XS_UNIVERSAL_can) SV *sv; char *name; SV *rv; - GV *gv; - CV *cvp; + HV *pkg = NULL; if (items != 2) croak("Usage: UNIVERSAL::can(object-ref, method)"); @@ -140,40 +140,22 @@ XS(XS_UNIVERSAL_can) name = (char *)SvPV(ST(1),na); rv = &sv_undef; - if(SvROK(sv) && (sv = (SV*)SvRV(sv)) && SvOBJECT(sv)) { - gv = gv_fetchmethod(SvSTASH(sv), name); - - if(gv && GvCV(gv)) { - /* If the sub is only a stub then we may have a gv to AUTOLOAD */ - GV **gvp = (GV**)hv_fetch(GvSTASH(gv), name, strlen(name), TRUE); - if(gvp && (cvp = GvCV(*gvp))) { - rv = sv_newmortal(); - sv_setsv(rv, newRV((SV*)cvp)); - } - } + if(SvROK(sv)) { + sv = (SV*)SvRV(sv); + if(SvOBJECT(sv)) + pkg = SvSTASH(sv); + } + else { + pkg = gv_stashsv(sv, FALSE); } - ST(0) = rv; - XSRETURN(1); -} - -static -XS(XS_UNIVERSAL_is_instance) -{ - dXSARGS; - ST(0) = SvROK(ST(0)) ? &sv_yes : &sv_no; - XSRETURN(1); -} - -static -XS(XS_UNIVERSAL_class) -{ - dXSARGS; - if(SvROK(ST(0))) { - SV *sv = sv_newmortal(); - sv_setpv(sv, HvNAME(SvSTASH(ST(0)))); - ST(0) = sv; + if (pkg) { + GV *gv = gv_fetchmethod_autoload(pkg, name, FALSE); + if (gv && isGV(gv)) + rv = sv_2mortal(newRV((SV*)GvCV(gv))); } + + ST(0) = rv; XSRETURN(1); } @@ -186,6 +168,7 @@ XS(XS_UNIVERSAL_VERSION) GV *gv; SV *sv; char *undef; + double req; if(SvROK(ST(0))) { sv = (SV*)SvRV(ST(0)); @@ -210,9 +193,9 @@ XS(XS_UNIVERSAL_VERSION) undef = "(undef)"; } - if(items > 1 && (undef || SvNV(ST(1)) > SvNV(sv))) + if (items > 1 && (undef || (req = SvNV(ST(1)), req > SvNV(sv)))) croak("%s version %s required--this is only version %s", - HvNAME(pkg),SvPV(ST(1),na),undef ? undef : SvPV(sv,na)); + HvNAME(pkg), SvPV(ST(1),na), undef ? undef : SvPV(sv,na)); ST(0) = sv; @@ -226,7 +209,5 @@ boot_core_UNIVERSAL() newXS("UNIVERSAL::isa", XS_UNIVERSAL_isa, file); newXS("UNIVERSAL::can", XS_UNIVERSAL_can, file); - newXS("UNIVERSAL::class", XS_UNIVERSAL_class, file); - newXS("UNIVERSAL::is_instance", XS_UNIVERSAL_is_instance, file); newXS("UNIVERSAL::VERSION", XS_UNIVERSAL_VERSION, file); }