Commit | Line | Data |
e0e4674a |
1 | |
2 | #include "EXTERN.h" |
3 | #include "perl.h" |
4 | #include "XSUB.h" |
15273f3c |
5 | |
599791aa |
6 | #define NEED_sv_2pv_flags |
15273f3c |
7 | #define NEED_sv_2pv_nolen |
b0e94057 |
8 | #include "ppport.h" |
e0e4674a |
9 | |
cc856b56 |
10 | SV *key_name; |
11 | U32 hash_name; |
12 | |
13 | SV *key_package; |
14 | U32 hash_package; |
15 | |
16 | SV *key_body; |
17 | U32 hash_body; |
18 | |
e0e4674a |
19 | /* |
e0e4674a |
20 | get_code_info: |
21 | Pass in a coderef, returns: |
22 | [ $pkg_name, $coderef_name ] ie: |
23 | [ 'Foo::Bar', 'new' ] |
24 | */ |
25 | |
26 | MODULE = Class::MOP PACKAGE = Class::MOP |
27 | |
cc856b56 |
28 | BOOT: |
29 | key_name = newSVpvs("name"); |
30 | key_body = newSVpvs("body"); |
31 | key_package = newSVpvs("package"); |
32 | |
33 | PERL_HASH(hash_name, "name", 4); |
34 | PERL_HASH(hash_body, "body", 4); |
35 | PERL_HASH(hash_package, "package", 7); |
36 | |
37 | |
d7bf3478 |
38 | PROTOTYPES: ENABLE |
39 | |
cc856b56 |
40 | |
e0e4674a |
41 | void |
42 | get_code_info(coderef) |
43 | SV* coderef |
44 | PREINIT: |
45 | char* name; |
46 | char* pkg; |
47 | PPCODE: |
e0e4674a |
48 | if( SvOK(coderef) && SvROK(coderef) && SvTYPE(SvRV(coderef)) == SVt_PVCV){ |
49 | coderef = SvRV(coderef); |
7b62d87f |
50 | /* I think this only gets triggered with a mangled coderef, but if |
51 | we hit it without the guard, we segfault. The slightly odd return |
52 | value strikes me as an improvement (mst) |
53 | */ |
a4f4221a |
54 | #ifdef isGV_with_GP |
55 | if ( isGV_with_GP(CvGV(coderef))) { |
56 | #endif |
7b62d87f |
57 | pkg = HvNAME( GvSTASH(CvGV(coderef)) ); |
58 | name = GvNAME( CvGV(coderef) ); |
a4f4221a |
59 | #ifdef isGV_with_GP |
60 | } else { |
61 | pkg = "__UNKNOWN__"; |
62 | name = "__ANON__"; |
63 | } |
64 | #endif |
e0e4674a |
65 | |
66 | EXTEND(SP, 2); |
67 | PUSHs(newSVpvn(pkg, strlen(pkg))); |
68 | PUSHs(newSVpvn(name, strlen(name))); |
69 | } |
70 | |
15273f3c |
71 | |
72 | MODULE = Class::MOP PACKAGE = Class::MOP::Package |
73 | |
74 | void |
cc856b56 |
75 | get_all_package_symbols(self, ...) |
76 | SV *self |
15273f3c |
77 | PROTOTYPE: $;$ |
78 | PREINIT: |
cc856b56 |
79 | HV *stash = NULL; |
15273f3c |
80 | SV *type_filter = NULL; |
75705e60 |
81 | register HE *he; |
15273f3c |
82 | PPCODE: |
83 | |
84 | switch ( GIMME_V ) { |
85 | case G_VOID: return; break; |
86 | case G_SCALAR: ST(0) = &PL_sv_undef; return; break; |
87 | } |
88 | |
89 | if ( items > 1 ) type_filter = ST(1); |
90 | |
91 | PUTBACK; |
92 | |
75705e60 |
93 | if (SvROK(self) && (he = hv_fetch_ent((HV *)SvRV(self), key_package, 0, hash_package))) |
94 | stash = gv_stashsv(HeVAL(he),0); |
15273f3c |
95 | |
96 | if ( stash ) { |
15273f3c |
97 | |
98 | (void)hv_iterinit(stash); |
99 | |
100 | if ( type_filter && SvPOK(type_filter) ) { |
101 | const char *const type = SvPV_nolen(type_filter); |
102 | |
103 | |
75705e60 |
104 | while ((he = hv_iternext(stash))) { |
105 | SV *const gv = HeVAL(he); |
15273f3c |
106 | SV *sv; |
107 | char *package = HvNAME(stash); |
108 | STRLEN pkglen = strlen(package); |
75705e60 |
109 | char *key; |
110 | STRLEN keylen; |
15273f3c |
111 | char *fq; |
112 | STRLEN fqlen; |
113 | |
15273f3c |
114 | switch( SvTYPE(gv) ) { |
115 | case SVt_PVGV: |
116 | switch (*type) { |
117 | case 'C': sv = (SV *)GvCVu(gv); break; /* CODE */ |
118 | case 'A': sv = (SV *)GvAV(gv); break; /* ARRAY */ |
119 | case 'I': sv = (SV *)GvIO(gv); break; /* IO */ |
120 | case 'H': sv = (SV *)GvHV(gv); break; /* HASH */ |
121 | case 'S': sv = (SV *)GvSV(gv); break; /* SCALAR */ |
122 | default: |
123 | croak("Unknown type %s\n", type); |
124 | } |
125 | break; |
126 | case SVt_RV: |
127 | /* BAH! constants are horrible */ |
75705e60 |
128 | key = HePV(he, keylen); |
129 | fqlen = pkglen + keylen + 3; |
15273f3c |
130 | fq = (char *)alloca(fqlen); |
75705e60 |
131 | snprintf(fq, fqlen, "%s::%s", package, key); |
cc856b56 |
132 | sv = (SV*)get_cv(fq, 0); |
75705e60 |
133 | sv_2mortal(sv); |
15273f3c |
134 | break; |
135 | default: |
136 | continue; |
137 | } |
138 | |
139 | if ( sv ) { |
75705e60 |
140 | SV *key = hv_iterkeysv(he); |
15273f3c |
141 | SPAGAIN; |
142 | EXTEND(SP, 2); |
143 | PUSHs(key); |
66af67fe |
144 | PUSHs(sv_2mortal(newRV_inc(sv))); |
15273f3c |
145 | PUTBACK; |
146 | } |
147 | } |
148 | } else { |
149 | EXTEND(SP, HvKEYS(stash) * 2); |
150 | |
75705e60 |
151 | while ((he = hv_iternext(stash))) { |
152 | SV *key = hv_iterkeysv(he); |
599791aa |
153 | SV *sv = HeVAL(he); |
15273f3c |
154 | SPAGAIN; |
0eb2957d |
155 | PUSHs(key); |
15273f3c |
156 | PUSHs(sv); |
157 | PUTBACK; |
158 | } |
159 | } |
160 | |
161 | } |
162 | |
cc856b56 |
163 | SV * |
164 | name(self) |
165 | SV *self |
166 | PREINIT: |
167 | register HE *he; |
168 | PPCODE: |
169 | if (SvROK(self) && (he = hv_fetch_ent((HV *)SvRV(self), key_package, 0, hash_package))) |
170 | XPUSHs(HeVAL(he)); |
171 | else |
172 | ST(0) = &PL_sv_undef; |
173 | |
174 | MODULE = Class::MOP PACKAGE = Class::Attribute |
175 | |
176 | SV * |
177 | name(self) |
178 | SV *self |
179 | PREINIT: |
180 | register HE *he; |
181 | PPCODE: |
182 | if (SvROK(self) && (he = hv_fetch_ent((HV *)SvRV(self), key_name, 0, hash_name))) |
183 | XPUSHs(HeVAL(he)); |
184 | else |
185 | ST(0) = &PL_sv_undef; |
186 | |
187 | MODULE = Class::MOP PACKAGE = Class::Method |
188 | |
189 | SV * |
190 | name(self) |
191 | SV *self |
192 | PREINIT: |
193 | register HE *he; |
194 | PPCODE: |
195 | if (SvROK(self) && (he = hv_fetch_ent((HV *)SvRV(self), key_name, 0, hash_name))) |
196 | XPUSHs(HeVAL(he)); |
197 | else |
198 | ST(0) = &PL_sv_undef; |
199 | |
200 | SV * |
201 | body(self) |
202 | SV *self |
203 | PREINIT: |
204 | register HE *he; |
205 | PPCODE: |
206 | if (SvROK(self) && (he = hv_fetch_ent((HV *)SvRV(self), key_body, 0, hash_body))) |
207 | XPUSHs(HeVAL(he)); |
208 | else |
209 | ST(0) = &PL_sv_undef; |