ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Devel-FindRef/FindRef.xs
Revision: 1.8
Committed: Sun Apr 27 05:59:06 2008 UTC (16 years ago) by root
Branch: MAIN
Changes since 1.7: +19 -7 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.6 #define res_pair(text) \
16 root 1.8 do { \
17 root 1.6 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.8 } while (0)
24 root 1.1
25 root 1.6 #define res_gv(sigil) \
26 root 1.8 do { \
27 root 1.6 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.8 } while (0)
34 root 1.1
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.8 /* Anonymous subs have a padlist but zero depth */
125     if (!depth && CvPADLIST (sv))
126 root 1.7 depth = 1;
127    
128 root 1.6 if (depth)
129     {
130     AV *padlist = CvPADLIST (sv);
131    
132     while (depth)
133     {
134     AV *pad = (AV *)AvARRAY (padlist)[depth];
135    
136     av_push (excl, newSVuv (PTR2UV (pad))); /* exclude pads themselves from being found */
137    
138 root 1.7 for (i = AvFILLp (pad) + 1; i--; )
139 root 1.6 if (AvARRAY (pad)[i] == targ)
140 root 1.8 {
141     /* Values from constant functions are stored in the pad without any name */
142     SV *name_sv = AvARRAY (AvARRAY (padlist)[0])[i];
143    
144     if (name_sv && SvPOK (name_sv))
145     res_pair (form ("in the lexical '%s' in", SvPVX (name_sv)));
146     else
147     res_pair ("in an unnamed lexical in");
148     }
149 root 1.6
150     --depth;
151     }
152     }
153 root 1.7
154 root 1.8 if (CvCONST (sv) && (SV*)CvXSUBANY (sv).any_ptr == targ)
155     res_pair ("the constant value of");
156    
157     if (!CvWEAKOUTSIDE (sv) && (SV*)CvOUTSIDE (sv) == targ)
158 root 1.7 res_pair ("the containing scope for");
159 root 1.2 }
160 root 1.6
161     break;
162    
163     case SVt_PVGV:
164     if (GvGP (sv))
165     {
166     if (GvSV (sv) == (SV *)targ) res_gv ('$');
167     if (GvAV (sv) == (AV *)targ) res_gv ('@');
168     if (GvHV (sv) == (HV *)targ) res_gv ('%');
169     if (GvCV (sv) == (CV *)targ) res_gv ('&');
170     }
171    
172     break;
173     }
174 root 1.1
175     if (rmagical)
176 root 1.5 SvRMAGICAL_on (sv);
177 root 1.1 }
178     }
179    
180     EXTEND (SP, 2);
181     PUSHs (sv_2mortal (newRV_noinc ((SV *)about)));
182     PUSHs (sv_2mortal (newRV_noinc ((SV *)excl)));
183     }
184