3493565bc7febf1088c5c4ee91f290163cc915e9
[p5sagit/p5-mst-13.2.git] / xsutils.c
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
9 /* package attributes; */
10 void XS_attributes__warn_reserved(pTHXo_ CV *cv);
11 void XS_attributes_reftype(pTHXo_ CV *cv);
12 void XS_attributes__modify_attrs(pTHXo_ CV *cv);
13 void XS_attributes__guess_stash(pTHXo_ CV *cv);
14 void XS_attributes__fetch_attrs(pTHXo_ CV *cv);
15 void 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 *.pm files is in a version-specific directory,
27  * version checks in these bootstrap calls are optional.
28  */
29
30 void
31 Perl_boot_core_xsutils(pTHX)
32 {
33     char *file = __FILE__;
34
35     newXS("attributes::bootstrap",      XS_attributes_bootstrap,        file);
36 }
37
38 #include "XSUB.h"
39
40 static int
41 modify_SV_attributes(pTHXo_ SV *sv, SV **retlist, SV **attrlist, int numattrs)
42 {
43     SV *attr;
44     char *name;
45     STRLEN len;
46     bool negated;
47     int nret;
48
49     for (nret = 0 ; numattrs && (attr = *attrlist++); numattrs--) {
50         name = SvPV(attr, len);
51         if ((negated = (*name == '-'))) {
52             name++;
53             len--;
54         }
55         switch (SvTYPE(sv)) {
56         case SVt_PVCV:
57             switch ((int)len) {
58             case 6:
59                 switch (*name) {
60                 case 'l':
61 #ifdef CVf_LVALUE
62                     if (strEQ(name, "lvalue")) {
63                         if (negated)
64                             CvFLAGS((CV*)sv) &= ~CVf_LVALUE;
65                         else
66                             CvFLAGS((CV*)sv) |= CVf_LVALUE;
67                         continue;
68                     }
69 #endif /* defined CVf_LVALUE */
70                     if (strEQ(name, "locked")) {
71                         if (negated)
72                             CvFLAGS((CV*)sv) &= ~CVf_LOCKED;
73                         else
74                             CvFLAGS((CV*)sv) |= CVf_LOCKED;
75                         continue;
76                     }
77                     break;
78                 case 'm':
79                     if (strEQ(name, "method")) {
80                         if (negated)
81                             CvFLAGS((CV*)sv) &= ~CVf_METHOD;
82                         else
83                             CvFLAGS((CV*)sv) |= CVf_METHOD;
84                         continue;
85                     }
86                     break;
87                 case 's':
88                     if (strEQ(name, "shared")) {
89                         if (negated)
90                             GvSHARED_off(CvGV((CV*)sv));
91                         else
92                             GvSHARED_on(CvGV((CV*)sv));
93                         continue;
94                     }
95                     break;
96                 }
97                 break;
98             }
99             break;
100         default:
101             switch ((int)len) {
102               case 6:
103                 switch (*name) {
104                   case 's':
105                     if (strEQ(name, "shared")) {
106                         /* toke.c has already marked as GvSHARED */
107                         continue;
108                     }
109                 }
110             }
111             break;
112         }
113         /* anything recognized had a 'continue' above */
114         *retlist++ = attr;
115         nret++;
116     }
117
118     return nret;
119 }
120
121
122
123 /* package attributes; */
124
125 XS(XS_attributes_bootstrap)
126 {
127     dXSARGS;
128     char *file = __FILE__;
129
130     newXSproto("attributes::_warn_reserved", XS_attributes__warn_reserved, file, "");
131     newXS("attributes::_modify_attrs",  XS_attributes__modify_attrs,    file);
132     newXSproto("attributes::_guess_stash", XS_attributes__guess_stash, file, "$");
133     newXSproto("attributes::_fetch_attrs", XS_attributes__fetch_attrs, file, "$");
134     newXSproto("attributes::reftype",   XS_attributes_reftype,  file, "$");
135
136     XSRETURN(0);
137 }
138
139 XS(XS_attributes__modify_attrs)
140 {
141     dXSARGS;
142     SV *rv, *sv;
143
144     if (items < 1) {
145 usage:
146         Perl_croak(aTHX_
147                    "Usage: attributes::_modify_attrs $reference, @attributes");
148     }
149
150     rv = ST(0);
151     if (!(SvOK(rv) && SvROK(rv)))
152         goto usage;
153     sv = SvRV(rv);
154     if (items > 1)
155         XSRETURN(modify_SV_attributes(aTHXo_ sv, &ST(0), &ST(1), items-1));
156
157     XSRETURN(0);
158 }
159
160 XS(XS_attributes__fetch_attrs)
161 {
162     dXSARGS;
163     SV *rv, *sv;
164     cv_flags_t cvflags;
165
166     if (items != 1) {
167 usage:
168         Perl_croak(aTHX_
169                    "Usage: attributes::_fetch_attrs $reference");
170     }
171
172     rv = ST(0);
173     SP -= items;
174     if (!(SvOK(rv) && SvROK(rv)))
175         goto usage;
176     sv = SvRV(rv);
177
178     switch (SvTYPE(sv)) {
179     case SVt_PVCV:
180         cvflags = CvFLAGS((CV*)sv);
181         if (cvflags & CVf_LOCKED)
182             XPUSHs(sv_2mortal(newSVpvn("locked", 6)));
183 #ifdef CVf_LVALUE
184         if (cvflags & CVf_LVALUE)
185             XPUSHs(sv_2mortal(newSVpvn("lvalue", 6)));
186 #endif
187         if (cvflags & CVf_METHOD)
188             XPUSHs(sv_2mortal(newSVpvn("method", 6)));
189         if (GvSHARED(CvGV((CV*)sv)))
190             XPUSHs(sv_2mortal(newSVpvn("shared", 6)));
191         break;
192     default:
193         break;
194     }
195
196     PUTBACK;
197 }
198
199 XS(XS_attributes__guess_stash)
200 {
201     dXSARGS;
202     SV *rv, *sv;
203 #ifdef dXSTARGET
204     dXSTARGET;
205 #else
206     SV * TARG = sv_newmortal();
207 #endif
208
209     if (items != 1) {
210 usage:
211         Perl_croak(aTHX_
212                    "Usage: attributes::_guess_stash $reference");
213     }
214
215     rv = ST(0);
216     ST(0) = TARG;
217     if (!(SvOK(rv) && SvROK(rv)))
218         goto usage;
219     sv = SvRV(rv);
220
221     if (SvOBJECT(sv))
222         sv_setpv(TARG, HvNAME(SvSTASH(sv)));
223 #if 0   /* this was probably a bad idea */
224     else if (SvPADMY(sv))
225         sv_setsv(TARG, &PL_sv_no);      /* unblessed lexical */
226 #endif
227     else {
228         HV *stash = Nullhv;
229         switch (SvTYPE(sv)) {
230         case SVt_PVCV:
231             if (CvGV(sv) && isGV(CvGV(sv)) && GvSTASH(CvGV(sv)) &&
232                             HvNAME(GvSTASH(CvGV(sv))))
233                 stash = GvSTASH(CvGV(sv));
234             else if (/* !CvANON(sv) && */ CvSTASH(sv) && HvNAME(CvSTASH(sv)))
235                 stash = CvSTASH(sv);
236             break;
237         case SVt_PVMG:
238             if (!(SvFAKE(sv) && SvTIED_mg(sv, PERL_MAGIC_glob)))
239                 break;
240             /*FALLTHROUGH*/
241         case SVt_PVGV:
242             if (GvGP(sv) && GvESTASH((GV*)sv) && HvNAME(GvESTASH((GV*)sv)))
243                 stash = GvESTASH((GV*)sv);
244             break;
245         default:
246             break;
247         }
248         if (stash)
249             sv_setpv(TARG, HvNAME(stash));
250     }
251
252 #ifdef dXSTARGET
253     SvSETMAGIC(TARG);
254 #endif
255     XSRETURN(1);
256 }
257
258 XS(XS_attributes_reftype)
259 {
260     dXSARGS;
261     SV *rv, *sv;
262 #ifdef dXSTARGET
263     dXSTARGET;
264 #else
265     SV * TARG = sv_newmortal();
266 #endif
267
268     if (items != 1) {
269 usage:
270         Perl_croak(aTHX_
271                    "Usage: attributes::reftype $reference");
272     }
273
274     rv = ST(0);
275     ST(0) = TARG;
276     if (SvGMAGICAL(rv))
277         mg_get(rv);
278     if (!(SvOK(rv) && SvROK(rv)))
279         goto usage;
280     sv = SvRV(rv);
281     sv_setpv(TARG, sv_reftype(sv, 0));
282 #ifdef dXSTARGET
283     SvSETMAGIC(TARG);
284 #endif
285
286     XSRETURN(1);
287 }
288
289 XS(XS_attributes__warn_reserved)
290 {
291     dXSARGS;
292 #ifdef dXSTARGET
293     dXSTARGET;
294 #else
295     SV * TARG = sv_newmortal();
296 #endif
297
298     if (items != 0) {
299         Perl_croak(aTHX_
300                    "Usage: attributes::_warn_reserved ()");
301     }
302
303     EXTEND(SP,1);
304     ST(0) = TARG;
305     sv_setiv(TARG, ckWARN(WARN_RESERVED) != 0);
306 #ifdef dXSTARGET
307     SvSETMAGIC(TARG);
308 #endif
309
310     XSRETURN(1);
311 }
312