--- Devel-FindRef/FindRef.xs 2007/01/11 23:05:52 1.2 +++ Devel-FindRef/FindRef.xs 2008/04/26 03:15:28 1.7 @@ -2,22 +2,34 @@ #include "perl.h" #include "XSUB.h" -#define res_pair(text) \ - { \ - AV *av = newAV (); \ - av_push (av, newSVpv (text, 0)); \ - av_push (av, newRV_inc (sv)); \ - av_push (about, newRV_noinc ((SV *)av)); \ +#define PERL_VERSION_ATLEAST(a,b,c) \ + (PERL_REVISION > (a) \ + || (PERL_REVISION == (a) \ + && (PERL_VERSION > (b) \ + || (PERL_VERSION == (b) && PERLSUBVERSION >= (c))))) + +#if !PERL_VERSION_ATLEAST (5,8,9) +# define SVt_LAST 16 +#endif + +#define res_pair(text) \ + { \ + AV *av = newAV (); \ + av_push (av, newSVpv (text, 0)); \ + if (rmagical) SvRMAGICAL_on (sv); \ + av_push (av, sv_rvweaken (newRV_inc (sv))); \ + if (rmagical) SvRMAGICAL_off (sv); \ + av_push (about, newRV_noinc ((SV *)av)); \ } -#define res_gv(sigil) \ - { \ - AV *av = newAV (); \ +#define res_gv(sigil) \ + { \ + AV *av = newAV (); \ av_push (av, newSVpv (form ("in the global %c%s::%.*s", sigil, \ - HvNAME (GvSTASH (sv)), \ + HvNAME (GvSTASH (sv)), \ GvNAMELEN (sv), GvNAME (sv) ? GvNAME (sv) : ""), \ - 0)); \ - av_push (about, newRV_noinc ((SV *)av)); \ + 0)); \ + av_push (about, newRV_noinc ((SV *)av)); \ } MODULE = Devel::FindRef PACKAGE = Devel::FindRef @@ -41,7 +53,7 @@ AV *excl = newAV (); if (!SvROK (target)) - croak ("about expects a reference to a perl value"); + croak ("find expects a reference to a perl value"); targ = SvRV (target); @@ -69,6 +81,7 @@ { if (mg->mg_obj == targ) res_pair (form ("referenced (in mg_obj) by '%c' type magic attached to", mg->mg_type)); + if ((SV *)mg->mg_ptr == targ && mg->mg_flags & MGf_REFCOUNTED) res_pair (form ("referenced (in mg_ptr) by '%c' type magic attached to", mg->mg_type)); @@ -76,67 +89,79 @@ } } - switch (SvTYPE (sv)) + if (SvROK (sv)) { - case SVt_RV: - if (sv != target && SvRV (sv) == targ) - res_pair ("referenced by"); - break; - - case SVt_PVAV: - if (AvREAL (sv)) - for (i = AvFILLp (sv) + 1; i--; ) - if (AvARRAY (sv)[i] == targ) - res_pair (form ("in array element %d of", i)); - break; + if (sv != target && SvRV (sv) == targ && !SvWEAKREF (sv)) + res_pair ("referenced by"); + } + else + switch (SvTYPE (sv)) + { + case SVt_PVAV: + if (AvREAL (sv)) + for (i = AvFILLp (sv) + 1; i--; ) + if (AvARRAY (sv)[i] == targ) + res_pair (form ("in array element %d of", i)); - case SVt_PVHV: - if (hv_iterinit ((HV *)sv)) - { - HE *he; - while ((he = hv_iternext ((HV *)sv))) - if (HeVAL (he) == targ) - res_pair (form ("in the member '%.*s' of", HeKLEN (he), HeKEY (he))); - } - break; + break; - case SVt_PVCV: - { - int depth = CvDEPTH (sv); - if (depth) + case SVt_PVHV: + if (hv_iterinit ((HV *)sv)) { - AV *padlist = CvPADLIST (sv); - while (depth) - { - AV *pad = (AV *)AvARRAY (padlist)[depth]; - av_push (excl, newSVuv (PTR2UV (pad))); /* exclude pads from being found */ - for (i = AvFILLp (pad); i--; ) - if (AvARRAY (pad)[i] == targ) - res_pair (form ("in the lexical '%s' in", SvPVX (AvARRAY (AvARRAY (padlist)[0])[i]))); + HE *he; - --depth; - } + while ((he = hv_iternext ((HV *)sv))) + if (HeVAL (he) == targ) + res_pair (form ("in the member '%.*s' of", HeKLEN (he), HeKEY (he))); } - } - break; - case SVt_PVGV: - if (GvGP (sv)) + break; + + case SVt_PVCV: { - if (GvSV (sv) == targ) - res_gv ('$'); - if (GvAV (sv) == (AV *)targ) - res_gv ('@'); - if (GvHV (sv) == (HV *)targ) - res_gv ('%'); - if (GvCV (sv) == (CV *)targ) - res_gv ('&'); + int depth = CvDEPTH (sv); + + if (!depth && CvPADLIST(sv)) + depth = 1; + + if (depth) + { + AV *padlist = CvPADLIST (sv); + + while (depth) + { + AV *pad = (AV *)AvARRAY (padlist)[depth]; + + av_push (excl, newSVuv (PTR2UV (pad))); /* exclude pads themselves from being found */ + + for (i = AvFILLp (pad) + 1; i--; ) + if (AvARRAY (pad)[i] == targ) + res_pair (form ("in the lexical '%s' in", SvPVX (AvARRAY (AvARRAY (padlist)[0])[i]))); + + --depth; + } + } + + if ((SV*)CvOUTSIDE(sv) == targ) + res_pair ("the containing scope for"); } - break; - } + + break; + + case SVt_PVGV: + if (GvGP (sv)) + { + if (GvSV (sv) == (SV *)targ) res_gv ('$'); + if (GvAV (sv) == (AV *)targ) res_gv ('@'); + if (GvHV (sv) == (HV *)targ) res_gv ('%'); + if (GvCV (sv) == (CV *)targ) res_gv ('&'); + } + + break; + } if (rmagical) - SvRMAGICAL_off (sv); + SvRMAGICAL_on (sv); } }