This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
(retracted by #14307)
[perl5.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(pTHX_ CV *cv);
11 void XS_attributes_reftype(pTHX_ CV *cv);
12 void XS_attributes__modify_attrs(pTHX_ CV *cv);
13 void XS_attributes__guess_stash(pTHX_ CV *cv);
14 void XS_attributes__fetch_attrs(pTHX_ CV *cv);
15 void XS_attributes_bootstrap(pTHX_ 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(pTHX_ 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 'u':
88                     if (strEQ(name, "unique")) {
89                         if (negated)
90                             GvUNIQUE_off(CvGV((CV*)sv));
91                         else
92                             GvUNIQUE_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 'u':
105                     if (strEQ(name, "unique")) {
106                         if (SvTYPE(sv) == SVt_PVGV) {
107                             if (negated)
108                                 GvUNIQUE_off(sv);
109                             else
110                                 GvUNIQUE_on(sv);
111                         }
112                         /* Hope this came from toke.c if not a GV. */
113                         continue;
114                     }
115                 }
116             }
117             break;
118         }
119         /* anything recognized had a 'continue' above */
120         *retlist++ = attr;
121         nret++;
122     }
123
124     return nret;
125 }
126
127
128
129 /* package attributes; */
130
131 XS(XS_attributes_bootstrap)
132 {
133     dXSARGS;
134     char *file = __FILE__;
135
136     if( items > 1 )
137         Perl_croak(aTHX_ "Usage: attributes::bootstrap $module");
138
139     newXSproto("attributes::_warn_reserved", XS_attributes__warn_reserved, file, "");
140     newXS("attributes::_modify_attrs",  XS_attributes__modify_attrs,    file);
141     newXSproto("attributes::_guess_stash", XS_attributes__guess_stash, file, "$");
142     newXSproto("attributes::_fetch_attrs", XS_attributes__fetch_attrs, file, "$");
143     newXSproto("attributes::reftype",   XS_attributes_reftype,  file, "$");
144
145     XSRETURN(0);
146 }
147
148 XS(XS_attributes__modify_attrs)
149 {
150     dXSARGS;
151     SV *rv, *sv;
152
153     if (items < 1) {
154 usage:
155         Perl_croak(aTHX_
156                    "Usage: attributes::_modify_attrs $reference, @attributes");
157     }
158
159     rv = ST(0);
160     if (!(SvOK(rv) && SvROK(rv)))
161         goto usage;
162     sv = SvRV(rv);
163     if (items > 1)
164         XSRETURN(modify_SV_attributes(aTHX_ sv, &ST(0), &ST(1), items-1));
165
166     XSRETURN(0);
167 }
168
169 XS(XS_attributes__fetch_attrs)
170 {
171     dXSARGS;
172     SV *rv, *sv;
173     cv_flags_t cvflags;
174
175     if (items != 1) {
176 usage:
177         Perl_croak(aTHX_
178                    "Usage: attributes::_fetch_attrs $reference");
179     }
180
181     rv = ST(0);
182     SP -= items;
183     if (!(SvOK(rv) && SvROK(rv)))
184         goto usage;
185     sv = SvRV(rv);
186
187     switch (SvTYPE(sv)) {
188     case SVt_PVCV:
189         cvflags = CvFLAGS((CV*)sv);
190         if (cvflags & CVf_LOCKED)
191             XPUSHs(sv_2mortal(newSVpvn("locked", 6)));
192 #ifdef CVf_LVALUE
193         if (cvflags & CVf_LVALUE)
194             XPUSHs(sv_2mortal(newSVpvn("lvalue", 6)));
195 #endif
196         if (cvflags & CVf_METHOD)
197             XPUSHs(sv_2mortal(newSVpvn("method", 6)));
198         if (GvUNIQUE(CvGV((CV*)sv)))
199             XPUSHs(sv_2mortal(newSVpvn("unique", 6)));
200         break;
201     case SVt_PVGV:
202         if (GvUNIQUE(sv))
203             XPUSHs(sv_2mortal(newSVpvn("unique", 6)));
204         break;
205     default:
206         break;
207     }
208
209     PUTBACK;
210 }
211
212 XS(XS_attributes__guess_stash)
213 {
214     dXSARGS;
215     SV *rv, *sv;
216 #ifdef dXSTARGET
217     dXSTARGET;
218 #else
219     SV * TARG = sv_newmortal();
220 #endif
221
222     if (items != 1) {
223 usage:
224         Perl_croak(aTHX_
225                    "Usage: attributes::_guess_stash $reference");
226     }
227
228     rv = ST(0);
229     ST(0) = TARG;
230     if (!(SvOK(rv) && SvROK(rv)))
231         goto usage;
232     sv = SvRV(rv);
233
234     if (SvOBJECT(sv))
235         sv_setpv(TARG, HvNAME(SvSTASH(sv)));
236 #if 0   /* this was probably a bad idea */
237     else if (SvPADMY(sv))
238         sv_setsv(TARG, &PL_sv_no);      /* unblessed lexical */
239 #endif
240     else {
241         HV *stash = Nullhv;
242         switch (SvTYPE(sv)) {
243         case SVt_PVCV:
244             if (CvGV(sv) && isGV(CvGV(sv)) && GvSTASH(CvGV(sv)))
245                 stash = GvSTASH(CvGV(sv));
246             else if (/* !CvANON(sv) && */ CvSTASH(sv))
247                 stash = CvSTASH(sv);
248             break;
249         case SVt_PVMG:
250             if (!(SvFAKE(sv) && SvTIED_mg(sv, PERL_MAGIC_glob)))
251                 break;
252             /*FALLTHROUGH*/
253         case SVt_PVGV:
254             if (GvGP(sv) && GvESTASH((GV*)sv))
255                 stash = GvESTASH((GV*)sv);
256             break;
257         default:
258             break;
259         }
260         if (stash)
261             sv_setpv(TARG, HvNAME(stash));
262     }
263
264 #ifdef dXSTARGET
265     SvSETMAGIC(TARG);
266 #endif
267     XSRETURN(1);
268 }
269
270 XS(XS_attributes_reftype)
271 {
272     dXSARGS;
273     SV *rv, *sv;
274 #ifdef dXSTARGET
275     dXSTARGET;
276 #else
277     SV * TARG = sv_newmortal();
278 #endif
279
280     if (items != 1) {
281 usage:
282         Perl_croak(aTHX_
283                    "Usage: attributes::reftype $reference");
284     }
285
286     rv = ST(0);
287     ST(0) = TARG;
288     if (SvGMAGICAL(rv))
289         mg_get(rv);
290     if (!(SvOK(rv) && SvROK(rv)))
291         goto usage;
292     sv = SvRV(rv);
293     sv_setpv(TARG, sv_reftype(sv, 0));
294 #ifdef dXSTARGET
295     SvSETMAGIC(TARG);
296 #endif
297
298     XSRETURN(1);
299 }
300
301 XS(XS_attributes__warn_reserved)
302 {
303     dXSARGS;
304 #ifdef dXSTARGET
305     dXSTARGET;
306 #else
307     SV * TARG = sv_newmortal();
308 #endif
309
310     if (items != 0) {
311         Perl_croak(aTHX_
312                    "Usage: attributes::_warn_reserved ()");
313     }
314
315     EXTEND(SP,1);
316     ST(0) = TARG;
317     sv_setiv(TARG, ckWARN(WARN_RESERVED) != 0);
318 #ifdef dXSTARGET
319     SvSETMAGIC(TARG);
320 #endif
321
322     XSRETURN(1);
323 }
324