ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Devel-FindRef/FindRef.xs
Revision: 1.7
Committed: Sat Apr 26 03:15:28 2008 UTC (16 years ago) by root
Branch: MAIN
CVS Tags: rel-1_2
Changes since 1.6: +9 -1 lines
Log Message:
1.2

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