ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Devel-FindRef/FindRef.xs
Revision: 1.6
Committed: Sat Dec 29 21:04:46 2007 UTC (16 years, 4 months ago) by root
Branch: MAIN
CVS Tags: rel-1_1
Changes since 1.5: +68 -61 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     { \
17     AV *av = newAV (); \
18     av_push (av, newSVpv (text, 0)); \
19     av_push (av, sv_rvweaken (newRV_inc (sv))); \
20     av_push (about, newRV_noinc ((SV *)av)); \
21 root 1.1 }
22    
23 root 1.6 #define res_gv(sigil) \
24     { \
25     AV *av = newAV (); \
26 root 1.1 av_push (av, newSVpv (form ("in the global %c%s::%.*s", sigil, \
27 root 1.6 HvNAME (GvSTASH (sv)), \
28 root 1.1 GvNAMELEN (sv), GvNAME (sv) ? GvNAME (sv) : "<anonymous>"), \
29 root 1.6 0)); \
30     av_push (about, newRV_noinc ((SV *)av)); \
31 root 1.1 }
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 root 1.6
83 root 1.2 if ((SV *)mg->mg_ptr == targ && mg->mg_flags & MGf_REFCOUNTED)
84     res_pair (form ("referenced (in mg_ptr) by '%c' type magic attached to", mg->mg_type));
85    
86     mg = mg->mg_moremagic;
87     }
88     }
89 root 1.1
90 root 1.6 if (SvROK (sv))
91 root 1.1 {
92 root 1.6 if (sv != target && SvRV (sv) == targ && !SvWEAKREF (sv))
93     res_pair ("referenced by");
94     }
95     else
96     switch (SvTYPE (sv))
97     {
98     case SVt_PVAV:
99     if (AvREAL (sv))
100     for (i = AvFILLp (sv) + 1; i--; )
101     if (AvARRAY (sv)[i] == targ)
102     res_pair (form ("in array element %d of", i));
103 root 1.1
104 root 1.6 break;
105 root 1.1
106 root 1.6 case SVt_PVHV:
107     if (hv_iterinit ((HV *)sv))
108 root 1.1 {
109 root 1.6 HE *he;
110 root 1.1
111 root 1.6 while ((he = hv_iternext ((HV *)sv)))
112     if (HeVAL (he) == targ)
113     res_pair (form ("in the member '%.*s' of", HeKLEN (he), HeKEY (he)));
114 root 1.1 }
115 root 1.2
116 root 1.6 break;
117    
118     case SVt_PVCV:
119 root 1.2 {
120 root 1.6 int depth = CvDEPTH (sv);
121    
122     if (depth)
123     {
124     AV *padlist = CvPADLIST (sv);
125    
126     while (depth)
127     {
128     AV *pad = (AV *)AvARRAY (padlist)[depth];
129    
130     av_push (excl, newSVuv (PTR2UV (pad))); /* exclude pads themselves from being found */
131    
132     for (i = AvFILLp (pad); i--; )
133     if (AvARRAY (pad)[i] == targ)
134     res_pair (form ("in the lexical '%s' in", SvPVX (AvARRAY (AvARRAY (padlist)[0])[i])));
135    
136     --depth;
137     }
138     }
139 root 1.2 }
140 root 1.6
141     break;
142    
143     case SVt_PVGV:
144     if (GvGP (sv))
145     {
146     if (GvSV (sv) == (SV *)targ) res_gv ('$');
147     if (GvAV (sv) == (AV *)targ) res_gv ('@');
148     if (GvHV (sv) == (HV *)targ) res_gv ('%');
149     if (GvCV (sv) == (CV *)targ) res_gv ('&');
150     }
151    
152     break;
153     }
154 root 1.1
155     if (rmagical)
156 root 1.5 SvRMAGICAL_on (sv);
157 root 1.1 }
158     }
159    
160     EXTEND (SP, 2);
161     PUSHs (sv_2mortal (newRV_noinc ((SV *)about)));
162     PUSHs (sv_2mortal (newRV_noinc ((SV *)excl)));
163     }
164