X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=universal.c;h=ef4f5b306676e6156b589c04b2805b451321c600;hb=7f61b687036bb8a098a2e70b387919a448b7bd62;hp=72087e62a89974a179f79f2526b9c15b76acbe02;hpb=bf3f28f2f1de2d93e00d5b74b50e8eaa798fc0c2;p=p5sagit%2Fp5-mst-13.2.git diff --git a/universal.c b/universal.c index 72087e6..ef4f5b3 100644 --- a/universal.c +++ b/universal.c @@ -1,18 +1,13 @@ #include "EXTERN.h" #include "perl.h" -#include "XSUB.h" /* * Contributed by Graham Barr * The main guts of traverse_isa was actually copied from gv_fetchmeth */ -static SV * -isa_lookup(stash, name, len, level) -HV *stash; -char *name; -int len; -int level; +STATIC SV * +isa_lookup(HV *stash, char *name, int len, int level) { AV* av; GV* gv; @@ -26,7 +21,7 @@ int level; return &sv_yes; if (level > 100) - croak("Recursive inheritance detected"); + croak("Recursive inheritance detected in package '%s'", HvNAME(stash)); gvp = (GV**)hv_fetch(stash, "::ISA::CACHE::", 14, FALSE); @@ -52,7 +47,8 @@ int level; } if(hv) { SV** svp = AvARRAY(av); - I32 items = AvFILL(av) + 1; + /* NOTE: No support for tied ISA */ + I32 items = AvFILLp(av) + 1; while (items--) { SV* sv = *svp++; HV* basestash = gv_stashsv(sv, FALSE); @@ -71,40 +67,59 @@ int level; } } - return &sv_no; + return boolSV(strEQ(name, "UNIVERSAL")); } -static -XS(XS_UNIVERSAL_isa) +bool +sv_derived_from(SV *sv, char *name) { - dXSARGS; - SV *sv, *rv; - char *name, *type; + SV *rv; + char *type; HV *stash; - - if (items != 2) - croak("Usage: UNIVERSAL::isa(reference, kind)"); - + stash = Nullhv; type = Nullch; - sv = ST(0); - name = (char *)SvPV(ST(1),na); + + if (SvGMAGICAL(sv)) + mg_get(sv) ; if (SvROK(sv)) { - sv = SvRV(sv); - type = sv_reftype(sv,0); - if(SvOBJECT(sv)) - stash = SvSTASH(sv); + sv = SvRV(sv); + type = sv_reftype(sv,0); + if(SvOBJECT(sv)) + stash = SvSTASH(sv); } else { - stash = gv_stashsv(sv, FALSE); + stash = gv_stashsv(sv, FALSE); } + + return (type && strEQ(type,name)) || + (stash && isa_lookup(stash, name, strlen(name), 0) == &sv_yes) + ? TRUE + : FALSE ; + +} + +#ifdef PERL_OBJECT +#define NO_XSLOCKS +#endif /* PERL_OBJECT */ + +#include "XSUB.h" + +static +XS(XS_UNIVERSAL_isa) +{ + dXSARGS; + SV *sv; + char *name; + + if (items != 2) + croak("Usage: UNIVERSAL::isa(reference, kind)"); - ST(0) = (type && strEQ(type,name)) || - (stash && isa_lookup(stash, name, strlen(name), 0) == &sv_yes) - ? &sv_yes - : &sv_no; + sv = ST(0); + name = (char *)SvPV(ST(1),na); + ST(0) = boolSV(sv_derived_from(sv, name)); XSRETURN(1); } @@ -115,8 +130,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)"); @@ -125,40 +139,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)) && SvOBJECT(SvRV(ST(0)))) { - SV *sv = sv_newmortal(); - sv_setpv(sv, HvNAME(SvSTASH(SvRV(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); } @@ -171,6 +167,7 @@ XS(XS_UNIVERSAL_VERSION) GV *gv; SV *sv; char *undef; + double req; if(SvROK(ST(0))) { sv = (SV*)SvRV(ST(0)); @@ -195,23 +192,27 @@ 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; XSRETURN(1); } +#ifdef PERL_OBJECT +#undef boot_core_UNIVERSAL +#define boot_core_UNIVERSAL CPerlObj::Perl_boot_core_UNIVERSAL +#define pPerl this +#endif + void -boot_core_UNIVERSAL() +boot_core_UNIVERSAL(void) { char *file = __FILE__; 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); }