From: Ilya Zakharevich <ilya@math.ohio-state.edu>
[p5sagit/p5-mst-13.2.git] / xsutils.c
CommitLineData
09bef843 1#include "EXTERN.h"
2#define PERL_IN_XSUTILS_C
3#include "perl.h"
4
5/*
6 * Contributed by Spider Boardman (spider.boardman@orb.nashua.nh.us).
7 */
8
349fd7b7 9/* package attributes; */
10void XS_attributes__warn_reserved(pTHXo_ CV *cv);
11void XS_attributes_reftype(pTHXo_ CV *cv);
12void XS_attributes__modify_attrs(pTHXo_ CV *cv);
13void XS_attributes__guess_stash(pTHXo_ CV *cv);
14void XS_attributes__fetch_attrs(pTHXo_ CV *cv);
15void XS_attributes_bootstrap(pTHXo_ CV *cv);
16
17
18/*
19 * Note that only ${pkg}::bootstrap definitions should go here.
20 * This helps keep down the start-up time, which is especially
21 * relevant for users who don't invoke any features which are
22 * (partially) implemented here.
23 *
24 * The various bootstrap definitions can take care of doing
25 * package-specific newXS() calls. Since the layout of the
26 * bundled lib/*.pm files is in a version-specific directory,
27 * version checks in these bootstrap calls are optional.
28 */
29
30void
31Perl_boot_core_xsutils(pTHX)
32{
33 char *file = __FILE__;
34
35 newXS("attributes::bootstrap", XS_attributes_bootstrap, file);
36}
37
38#ifdef PERL_OBJECT
39#define NO_XSLOCKS
40#endif /* PERL_OBJECT */
41
42#include "XSUB.h"
43
44static int
45modify_SV_attributes(pTHXo_ SV *sv, SV **retlist, SV **attrlist, int numattrs)
09bef843 46{
47 SV *attr;
48 char *name;
49 STRLEN len;
50 bool negated;
51 int nret;
52
53 for (nret = 0 ; numattrs && (attr = *attrlist++); numattrs--) {
54 name = SvPV(attr, len);
55 if (negated = (*name == '-')) {
56 name++;
57 len--;
58 }
59 switch (SvTYPE(sv)) {
60 case SVt_PVCV:
61 switch ((int)len) {
62 case 6:
63 switch (*name) {
64 case 'l':
65#ifdef CVf_LVALUE
66 if (strEQ(name, "lvalue")) {
67 if (negated)
68 CvFLAGS((CV*)sv) &= ~CVf_LVALUE;
69 else
70 CvFLAGS((CV*)sv) |= CVf_LVALUE;
71 continue;
72 }
73#endif /* defined CVf_LVALUE */
74 if (strEQ(name, "locked")) {
75 if (negated)
76 CvFLAGS((CV*)sv) &= ~CVf_LOCKED;
77 else
78 CvFLAGS((CV*)sv) |= CVf_LOCKED;
79 continue;
80 }
81 break;
82 case 'm':
83 if (strEQ(name, "method")) {
84 if (negated)
85 CvFLAGS((CV*)sv) &= ~CVf_METHOD;
86 else
87 CvFLAGS((CV*)sv) |= CVf_METHOD;
88 continue;
89 }
90 break;
91 }
92 break;
93 }
94 break;
95 default:
96 /* nothing, yet */
97 break;
98 }
99 /* anything recognized had a 'continue' above */
100 *retlist++ = attr;
101 nret++;
102 }
103
104 return nret;
105}
106
107
09bef843 108
109/* package attributes; */
110
111XS(XS_attributes_bootstrap)
112{
113 dXSARGS;
114 char *file = __FILE__;
115
116 newXSproto("attributes::_warn_reserved", XS_attributes__warn_reserved, file, "");
117 newXS("attributes::_modify_attrs", XS_attributes__modify_attrs, file);
118 newXSproto("attributes::_guess_stash", XS_attributes__guess_stash, file, "$");
119 newXSproto("attributes::_fetch_attrs", XS_attributes__fetch_attrs, file, "$");
120 newXSproto("attributes::reftype", XS_attributes_reftype, file, "$");
121
122 XSRETURN(0);
123}
124
125XS(XS_attributes__modify_attrs)
126{
127 dXSARGS;
128 SV *rv, *sv;
129
130 if (items < 1) {
131usage:
132 Perl_croak(aTHX_
133 "Usage: attributes::_modify_attrs $reference, @attributes");
134 }
135
136 rv = ST(0);
137 if (!(SvOK(rv) && SvROK(rv)))
138 goto usage;
139 sv = SvRV(rv);
140 if (items > 1)
349fd7b7 141 XSRETURN(modify_SV_attributes(aTHXo_ sv, &ST(0), &ST(1), items-1));
09bef843 142
143 XSRETURN(0);
144}
145
146XS(XS_attributes__fetch_attrs)
147{
148 dXSARGS;
149 SV *rv, *sv;
150 cv_flags_t cvflags;
151
152 if (items != 1) {
153usage:
154 Perl_croak(aTHX_
155 "Usage: attributes::_fetch_attrs $reference");
156 }
157
158 rv = ST(0);
159 SP -= items;
160 if (!(SvOK(rv) && SvROK(rv)))
161 goto usage;
162 sv = SvRV(rv);
163
164 switch (SvTYPE(sv)) {
165 case SVt_PVCV:
166 cvflags = CvFLAGS((CV*)sv);
167 if (cvflags & CVf_LOCKED)
168 XPUSHs(sv_2mortal(newSVpvn("locked", 6)));
169#ifdef CVf_LVALUE
170 if (cvflags & CVf_LVALUE)
171 XPUSHs(sv_2mortal(newSVpvn("lvalue", 6)));
172#endif
173 if (cvflags & CVf_METHOD)
174 XPUSHs(sv_2mortal(newSVpvn("method", 6)));
175 break;
176 default:
177 break;
178 }
179
180 PUTBACK;
181}
182
183XS(XS_attributes__guess_stash)
184{
185 dXSARGS;
186 SV *rv, *sv;
187#ifdef dXSTARGET
188 dXSTARGET;
189#else
190 SV * TARG = sv_newmortal();
191#endif
192
193 if (items != 1) {
194usage:
195 Perl_croak(aTHX_
196 "Usage: attributes::_guess_stash $reference");
197 }
198
199 rv = ST(0);
200 ST(0) = TARG;
201 if (!(SvOK(rv) && SvROK(rv)))
202 goto usage;
203 sv = SvRV(rv);
204
205 if (SvOBJECT(sv))
206 sv_setpv(TARG, HvNAME(SvSTASH(sv)));
207#if 0 /* this was probably a bad idea */
208 else if (SvPADMY(sv))
209 sv_setsv(TARG, &PL_sv_no); /* unblessed lexical */
210#endif
211 else {
212 HV *stash = Nullhv;
213 switch (SvTYPE(sv)) {
214 case SVt_PVCV:
215 if (CvGV(sv) && isGV(CvGV(sv)) && GvSTASH(CvGV(sv)) &&
216 HvNAME(GvSTASH(CvGV(sv))))
217 stash = GvSTASH(CvGV(sv));
218 else if (/* !CvANON(sv) && */ CvSTASH(sv) && HvNAME(CvSTASH(sv)))
219 stash = CvSTASH(sv);
220 break;
221 case SVt_PVMG:
222 if (!(SvFAKE(sv) && SvTIED_mg(sv, '*')))
223 break;
224 /*FALLTHROUGH*/
225 case SVt_PVGV:
226 if (GvGP(sv) && GvESTASH((GV*)sv) && HvNAME(GvESTASH((GV*)sv)))
227 stash = GvESTASH((GV*)sv);
228 break;
229 default:
230 break;
231 }
232 if (stash)
233 sv_setpv(TARG, HvNAME(stash));
234 }
235
236#ifdef dXSTARGET
237 SvSETMAGIC(TARG);
238#endif
239 XSRETURN(1);
240}
241
242XS(XS_attributes_reftype)
243{
244 dXSARGS;
245 SV *rv, *sv;
246#ifdef dXSTARGET
247 dXSTARGET;
248#else
249 SV * TARG = sv_newmortal();
250#endif
251
252 if (items != 1) {
253usage:
254 Perl_croak(aTHX_
255 "Usage: attributes::reftype $reference");
256 }
257
258 rv = ST(0);
259 ST(0) = TARG;
260 if (!SvOK(rv)) {
261 ST(0) = &PL_sv_no;
262 XSRETURN(1);
263 }
264 if (!SvROK(rv))
265 goto usage;
266 sv = SvRV(rv);
267 sv_setpv(TARG, sv_reftype(sv, 0));
268#ifdef dXSTARGET
269 SvSETMAGIC(TARG);
270#endif
271
272 XSRETURN(1);
273}
274
275XS(XS_attributes__warn_reserved)
276{
277 dXSARGS;
278 SV *rv, *sv;
279#ifdef dXSTARGET
280 dXSTARGET;
281#else
282 SV * TARG = sv_newmortal();
283#endif
284
285 if (items != 0) {
286 Perl_croak(aTHX_
287 "Usage: attributes::_warn_reserved ()");
288 }
289
290 EXTEND(SP,1);
291 ST(0) = TARG;
292 sv_setiv(TARG, ckWARN(WARN_RESERVED) != 0);
293#ifdef dXSTARGET
294 SvSETMAGIC(TARG);
295#endif
296
297 XSRETURN(1);
298}
299