ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Devel-FindRef/FindRef.xs
Revision: 1.4
Committed: Wed Feb 7 21:34:02 2007 UTC (17 years, 3 months ago) by root
Branch: MAIN
CVS Tags: rel-0_2
Changes since 1.3: +10 -0 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 #include "EXTERN.h"
2     #include "perl.h"
3     #include "XSUB.h"
4    
5 root 1.4 #define PERL_VERSION_ATLEAST(a,b,c) \
6     (PERL_REVISION > (a) \
7     || (PERL_REVISION == (a) \
8     && (PERL_VERSION > (b) \
9     || (PERL_VERSION == (b) && PERLSUBVERSION >= (c)))))
10    
11     #if !PERL_VERSION_ATLEAST (5,8,9)
12     # define SVt_LAST 16
13     #endif
14    
15 root 1.1 #define res_pair(text) \
16     { \
17     AV *av = newAV (); \
18     av_push (av, newSVpv (text, 0)); \
19     av_push (av, newRV_inc (sv)); \
20     av_push (about, newRV_noinc ((SV *)av)); \
21     }
22    
23     #define res_gv(sigil) \
24     { \
25     AV *av = newAV (); \
26     av_push (av, newSVpv (form ("in the global %c%s::%.*s", sigil, \
27     HvNAME (GvSTASH (sv)), \
28     GvNAMELEN (sv), GvNAME (sv) ? GvNAME (sv) : "<anonymous>"), \
29     0)); \
30     av_push (about, newRV_noinc ((SV *)av)); \
31     }
32    
33     MODULE = Devel::FindRef PACKAGE = Devel::FindRef
34    
35     PROTOTYPES: ENABLE
36    
37     SV *
38     ptr2ref (IV ptr)
39     CODE:
40     RETVAL = newRV_inc (INT2PTR (SV *, ptr));
41     OUTPUT:
42     RETVAL
43    
44     void
45     find_ (SV *target)
46     PPCODE:
47     {
48     SV *arena, *targ;
49     int rmagical, i;
50     AV *about = newAV ();
51     AV *excl = newAV ();
52    
53     if (!SvROK (target))
54 root 1.3 croak ("find expects a reference to a perl value");
55 root 1.1
56     targ = SvRV (target);
57    
58     for (arena = PL_sv_arenaroot; arena; arena = SvANY (arena))
59     {
60     UV idx = SvREFCNT (arena);
61    
62     /* Remember that the zeroth slot is used as the pointer onwards, so don't
63     include it. */
64     while (--idx > 0)
65     {
66     SV *sv = &arena [idx];
67 root 1.2
68     if (SvTYPE (sv) >= SVt_LAST)
69     continue;
70    
71     /* temporarily disable RMAGICAL, it can easily interfere with us */
72 root 1.1 if ((rmagical = SvRMAGICAL (sv)))
73     SvRMAGICAL_off (sv);
74    
75 root 1.2 if (SvTYPE (sv) >= SVt_PVMG)
76     {
77     MAGIC *mg = SvMAGIC (sv);
78     while (mg)
79     {
80     if (mg->mg_obj == targ)
81     res_pair (form ("referenced (in mg_obj) by '%c' type magic attached to", mg->mg_type));
82     if ((SV *)mg->mg_ptr == targ && mg->mg_flags & MGf_REFCOUNTED)
83     res_pair (form ("referenced (in mg_ptr) by '%c' type magic attached to", mg->mg_type));
84    
85     mg = mg->mg_moremagic;
86     }
87     }
88 root 1.1
89     switch (SvTYPE (sv))
90     {
91     case SVt_RV:
92     if (sv != target && SvRV (sv) == targ)
93     res_pair ("referenced by");
94     break;
95    
96     case SVt_PVAV:
97     if (AvREAL (sv))
98     for (i = AvFILLp (sv) + 1; i--; )
99     if (AvARRAY (sv)[i] == targ)
100     res_pair (form ("in array element %d of", i));
101     break;
102    
103     case SVt_PVHV:
104     if (hv_iterinit ((HV *)sv))
105     {
106     HE *he;
107     while ((he = hv_iternext ((HV *)sv)))
108     if (HeVAL (he) == targ)
109     res_pair (form ("in the member '%.*s' of", HeKLEN (he), HeKEY (he)));
110     }
111     break;
112    
113     case SVt_PVCV:
114     {
115     int depth = CvDEPTH (sv);
116     if (depth)
117     {
118     AV *padlist = CvPADLIST (sv);
119     while (depth)
120     {
121     AV *pad = (AV *)AvARRAY (padlist)[depth];
122     av_push (excl, newSVuv (PTR2UV (pad))); /* exclude pads from being found */
123     for (i = AvFILLp (pad); i--; )
124     if (AvARRAY (pad)[i] == targ)
125     res_pair (form ("in the lexical '%s' in", SvPVX (AvARRAY (AvARRAY (padlist)[0])[i])));
126    
127     --depth;
128     }
129     }
130     }
131     break;
132 root 1.2
133     case SVt_PVGV:
134     if (GvGP (sv))
135     {
136     if (GvSV (sv) == targ)
137     res_gv ('$');
138     if (GvAV (sv) == (AV *)targ)
139     res_gv ('@');
140     if (GvHV (sv) == (HV *)targ)
141     res_gv ('%');
142     if (GvCV (sv) == (CV *)targ)
143     res_gv ('&');
144     }
145     break;
146 root 1.1 }
147    
148     if (rmagical)
149     SvRMAGICAL_off (sv);
150     }
151     }
152    
153     EXTEND (SP, 2);
154     PUSHs (sv_2mortal (newRV_noinc ((SV *)about)));
155     PUSHs (sv_2mortal (newRV_noinc ((SV *)excl)));
156     }
157