--- Devel-FindRef/FindRef.xs 2008/04/27 05:59:06 1.8 +++ Devel-FindRef/FindRef.xs 2008/12/01 13:47:09 1.15 @@ -12,6 +12,10 @@ # define SVt_LAST 16 #endif +#if !PERL_VERSION_ATLEAST (5,10,0) +# define SvPAD_OUR(dummy) 0 +#endif + #define res_pair(text) \ do { \ AV *av = newAV (); \ @@ -22,40 +26,37 @@ av_push (about, newRV_noinc ((SV *)av)); \ } while (0) -#define res_gv(sigil) \ +#define res_text(text) \ do { \ AV *av = newAV (); \ - av_push (av, newSVpv (form ("in the global %c%s::%.*s", sigil, \ - HvNAME (GvSTASH (sv)), \ - GvNAMELEN (sv), GvNAME (sv) ? GvNAME (sv) : ""), \ - 0)); \ + av_push (av, newSVpv (text, 0)); \ av_push (about, newRV_noinc ((SV *)av)); \ } while (0) +#define res_gv(sigil) \ + res_text (form ("in the global %c%s::%.*s", sigil, \ + HvNAME (GvSTASH (sv)), \ + GvNAMELEN (sv), \ + GvNAME (sv) ? GvNAME (sv) : "")) + MODULE = Devel::FindRef PACKAGE = Devel::FindRef PROTOTYPES: ENABLE -SV * -ptr2ref (IV ptr) - CODE: - RETVAL = newRV_inc (INT2PTR (SV *, ptr)); - OUTPUT: - RETVAL - void -find_ (SV *target) +find_ (SV *target_ref) PPCODE: { SV *arena, *targ; - int rmagical, i; + U32 rmagical; + int i; AV *about = newAV (); AV *excl = newAV (); - if (!SvROK (target)) + if (!SvROK (target_ref)) croak ("find expects a reference to a perl value"); - targ = SvRV (target); + targ = SvRV (target_ref); for (arena = PL_sv_arenaroot; arena; arena = SvANY (arena)) { @@ -76,22 +77,32 @@ if (SvTYPE (sv) >= SVt_PVMG) { - MAGIC *mg = SvMAGIC (sv); - while (mg) + if (SvTYPE (sv) == SVt_PVMG && SvPAD_OUR (sv)) + { + /* I have no clue what this is */ + /* maybe some placeholder for our variables for eval? */ + /* it doesn't seem to reference anything, so we should be able to ignore it */ + } + else { - if (mg->mg_obj == targ) - res_pair (form ("referenced (in mg_obj) by '%c' type magic attached to", mg->mg_type)); + MAGIC *mg = SvMAGIC (sv); + + while (mg) + { + 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)); + 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)); - mg = mg->mg_moremagic; + mg = mg->mg_moremagic; + } } } if (SvROK (sv)) { - if (sv != target && SvRV (sv) == targ && !SvWEAKREF (sv)) + if (SvRV (sv) == targ && !SvWEAKREF (sv) && sv != target_ref) res_pair ("referenced by"); } else @@ -122,7 +133,7 @@ int depth = CvDEPTH (sv); /* Anonymous subs have a padlist but zero depth */ - if (!depth && CvPADLIST (sv)) + if (CvANON (sv) && !depth && CvPADLIST (sv)) depth = 1; if (depth) @@ -135,7 +146,11 @@ av_push (excl, newSVuv (PTR2UV (pad))); /* exclude pads themselves from being found */ - for (i = AvFILLp (pad) + 1; i--; ) + /* The 0th pad slot is @_ */ + if (AvARRAY (pad)[0] == targ) + res_pair ("the argument array for"); + + for (i = AvFILLp (pad) + 1; --i; ) if (AvARRAY (pad)[i] == targ) { /* Values from constant functions are stored in the pad without any name */ @@ -156,6 +171,17 @@ if (!CvWEAKOUTSIDE (sv) && (SV*)CvOUTSIDE (sv) == targ) res_pair ("the containing scope for"); + + if (sv == targ && CvANON (sv)) + if (CvSTART (sv) + && CvSTART (sv)->op_type == OP_NEXTSTATE + && CopLINE ((COP *)CvSTART (sv))) + res_text (form ("the closure created at %s:%d", + CopFILE ((COP *)CvSTART (sv)) ? CopFILE ((COP *)CvSTART (sv)) : "", + CopLINE ((COP *)CvSTART (sv)))); + else + res_text (form ("the closure created somewhere in file %s (PLEASE REPORT!)", + CvFILE (sv) ? CvFILE (sv) : "")); } break; @@ -177,8 +203,36 @@ } } + /* look at the mortalise stack of the current coroutine */ + for (i = 0; i <= PL_tmps_ix; ++i) + if (PL_tmps_stack [i] == targ) + res_text ("a temporary on the stack"); + + if (targ == (SV*)PL_main_cv) + res_text ("the main body of the program"); + EXTEND (SP, 2); PUSHs (sv_2mortal (newRV_noinc ((SV *)about))); PUSHs (sv_2mortal (newRV_noinc ((SV *)excl))); } +SV * +ptr2ref (UV ptr) + CODE: + RETVAL = newRV_inc (INT2PTR (SV *, ptr)); + OUTPUT: + RETVAL + +UV +ref2ptr (SV *rv) + CODE: + RETVAL = PTR2UV (SvRV (rv)); + OUTPUT: + RETVAL + +U32 +_refcnt (SV *rv) + CODE: + RETVAL = SvREFCNT (SvRV (rv)); + OUTPUT: + RETVAL