This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
add sv_reftype_len() and make sv_reftype() be a wrapper for it
[perl5.git] / universal.c
... / ...
CommitLineData
1/* universal.c
2 *
3 * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
4 * 2005, 2006, 2007, 2008 by Larry Wall and others
5 *
6 * You may distribute under the terms of either the GNU General Public
7 * License or the Artistic License, as specified in the README file.
8 *
9 */
10
11/*
12 * '"The roots of those mountains must be roots indeed; there must be
13 * great secrets buried there which have not been discovered since the
14 * beginning."' --Gandalf, relating Gollum's history
15 *
16 * [p.54 of _The Lord of the Rings_, I/ii: "The Shadow of the Past"]
17 */
18
19/* This file contains the code that implements the functions in Perl's
20 * UNIVERSAL package, such as UNIVERSAL->can().
21 *
22 * It is also used to store XS functions that need to be present in
23 * miniperl for a lack of a better place to put them. It might be
24 * clever to move them to seperate XS files which would then be pulled
25 * in by some to-be-written build process.
26 */
27
28#include "EXTERN.h"
29#define PERL_IN_UNIVERSAL_C
30#include "perl.h"
31
32#ifdef USE_PERLIO
33#include "perliol.h" /* For the PERLIO_F_XXX */
34#endif
35
36static HV *
37S_get_isa_hash(pTHX_ HV *const stash)
38{
39 dVAR;
40 struct mro_meta *const meta = HvMROMETA(stash);
41
42 PERL_ARGS_ASSERT_GET_ISA_HASH;
43
44 if (!meta->isa) {
45 AV *const isa = mro_get_linear_isa(stash);
46 if (!meta->isa) {
47 HV *const isa_hash = newHV();
48 /* Linearisation didn't build it for us, so do it here. */
49 SV *const *svp = AvARRAY(isa);
50 SV *const *const svp_end = svp + AvFILLp(isa) + 1;
51 const HEK *const canon_name = HvNAME_HEK(stash);
52
53 while (svp < svp_end) {
54 (void) hv_store_ent(isa_hash, *svp++, &PL_sv_undef, 0);
55 }
56
57 (void) hv_common(isa_hash, NULL, HEK_KEY(canon_name),
58 HEK_LEN(canon_name), HEK_FLAGS(canon_name),
59 HV_FETCH_ISSTORE, &PL_sv_undef,
60 HEK_HASH(canon_name));
61 (void) hv_store(isa_hash, "UNIVERSAL", 9, &PL_sv_undef, 0);
62
63 SvREADONLY_on(isa_hash);
64
65 meta->isa = isa_hash;
66 }
67 }
68 return meta->isa;
69}
70
71/*
72 * Contributed by Graham Barr <Graham.Barr@tiuk.ti.com>
73 * The main guts of traverse_isa was actually copied from gv_fetchmeth
74 */
75
76STATIC bool
77S_isa_lookup(pTHX_ HV *stash, const char * const name)
78{
79 dVAR;
80 const struct mro_meta *const meta = HvMROMETA(stash);
81 HV *const isa = meta->isa ? meta->isa : S_get_isa_hash(aTHX_ stash);
82 STRLEN len = strlen(name);
83 const HV *our_stash;
84
85 PERL_ARGS_ASSERT_ISA_LOOKUP;
86
87 if (hv_common(isa, NULL, name, len, 0 /* No "UTF-8" flag possible with only
88 a char * argument*/,
89 HV_FETCH_ISEXISTS, NULL, 0)) {
90 /* Direct name lookup worked. */
91 return TRUE;
92 }
93
94 /* A stash/class can go by many names (ie. User == main::User), so
95 we use the name in the stash itself, which is canonical. */
96 our_stash = gv_stashpvn(name, len, 0);
97
98 if (our_stash) {
99 HEK *const canon_name = HvNAME_HEK(our_stash);
100
101 if (hv_common(isa, NULL, HEK_KEY(canon_name), HEK_LEN(canon_name),
102 HEK_FLAGS(canon_name),
103 HV_FETCH_ISEXISTS, NULL, HEK_HASH(canon_name))) {
104 return TRUE;
105 }
106 }
107
108 return FALSE;
109}
110
111/*
112=head1 SV Manipulation Functions
113
114=for apidoc sv_derived_from
115
116Returns a boolean indicating whether the SV is derived from the specified class
117I<at the C level>. To check derivation at the Perl level, call C<isa()> as a
118normal Perl method.
119
120=cut
121*/
122
123bool
124Perl_sv_derived_from(pTHX_ SV *sv, const char *const name)
125{
126 dVAR;
127 HV *stash;
128
129 PERL_ARGS_ASSERT_SV_DERIVED_FROM;
130
131 SvGETMAGIC(sv);
132
133 if (SvROK(sv)) {
134 const char *type;
135 sv = SvRV(sv);
136 type = sv_reftype(sv,0);
137 if (type && strEQ(type,name))
138 return TRUE;
139 stash = SvOBJECT(sv) ? SvSTASH(sv) : NULL;
140 }
141 else {
142 stash = gv_stashsv(sv, 0);
143 }
144
145 return stash ? isa_lookup(stash, name) : FALSE;
146}
147
148/*
149=for apidoc sv_does
150
151Returns a boolean indicating whether the SV performs a specific, named role.
152The SV can be a Perl object or the name of a Perl class.
153
154=cut
155*/
156
157#include "XSUB.h"
158
159bool
160Perl_sv_does(pTHX_ SV *sv, const char *const name)
161{
162 const char *classname;
163 bool does_it;
164 SV *methodname;
165 dSP;
166
167 PERL_ARGS_ASSERT_SV_DOES;
168
169 ENTER;
170 SAVETMPS;
171
172 SvGETMAGIC(sv);
173
174 if (!SvOK(sv) || !(SvROK(sv) || (SvPOK(sv) && SvCUR(sv))
175 || (SvGMAGICAL(sv) && SvPOKp(sv) && SvCUR(sv)))) {
176 LEAVE;
177 return FALSE;
178 }
179
180 if (sv_isobject(sv)) {
181 classname = sv_reftype(SvRV(sv),TRUE);
182 } else {
183 classname = SvPV_nolen(sv);
184 }
185
186 if (strEQ(name,classname)) {
187 LEAVE;
188 return TRUE;
189 }
190
191 PUSHMARK(SP);
192 XPUSHs(sv);
193 mXPUSHs(newSVpv(name, 0));
194 PUTBACK;
195
196 methodname = newSVpvs_flags("isa", SVs_TEMP);
197 /* ugly hack: use the SvSCREAM flag so S_method_common
198 * can figure out we're calling DOES() and not isa(),
199 * and report eventual errors correctly. --rgs */
200 SvSCREAM_on(methodname);
201 call_sv(methodname, G_SCALAR | G_METHOD);
202 SPAGAIN;
203
204 does_it = SvTRUE( TOPs );
205 FREETMPS;
206 LEAVE;
207
208 return does_it;
209}
210
211/*
212=for apidoc croak_xs_usage
213
214A specialised variant of C<croak()> for emitting the usage message for xsubs
215
216 croak_xs_usage(cv, "eee_yow");
217
218works out the package name and subroutine name from C<cv>, and then calls
219C<croak()>. Hence if C<cv> is C<&ouch::awk>, it would call C<croak> as:
220
221 Perl_croak(aTHX_ "Usage: %s::%s(%s)", "ouch" "awk", "eee_yow");
222
223=cut
224*/
225
226void
227Perl_croak_xs_usage(pTHX_ const CV *const cv, const char *const params)
228{
229 const GV *const gv = CvGV(cv);
230
231 PERL_ARGS_ASSERT_CROAK_XS_USAGE;
232
233 if (gv) {
234 const char *const gvname = GvNAME(gv);
235 const HV *const stash = GvSTASH(gv);
236 const char *const hvname = stash ? HvNAME_get(stash) : NULL;
237
238 if (hvname)
239 Perl_croak(aTHX_ "Usage: %s::%s(%s)", hvname, gvname, params);
240 else
241 Perl_croak(aTHX_ "Usage: %s(%s)", gvname, params);
242 } else {
243 /* Pants. I don't think that it should be possible to get here. */
244 Perl_croak(aTHX_ "Usage: CODE(0x%"UVxf")(%s)", PTR2UV(cv), params);
245 }
246}
247
248XS(XS_UNIVERSAL_isa)
249{
250 dVAR;
251 dXSARGS;
252
253 if (items != 2)
254 croak_xs_usage(cv, "reference, kind");
255 else {
256 SV * const sv = ST(0);
257 const char *name;
258
259 SvGETMAGIC(sv);
260
261 if (!SvOK(sv) || !(SvROK(sv) || (SvPOK(sv) && SvCUR(sv))
262 || (SvGMAGICAL(sv) && SvPOKp(sv) && SvCUR(sv))))
263 XSRETURN_UNDEF;
264
265 name = SvPV_nolen_const(ST(1));
266
267 ST(0) = boolSV(sv_derived_from(sv, name));
268 XSRETURN(1);
269 }
270}
271
272XS(XS_UNIVERSAL_can)
273{
274 dVAR;
275 dXSARGS;
276 SV *sv;
277 const char *name;
278 SV *rv;
279 HV *pkg = NULL;
280
281 if (items != 2)
282 croak_xs_usage(cv, "object-ref, method");
283
284 sv = ST(0);
285
286 SvGETMAGIC(sv);
287
288 if (!SvOK(sv) || !(SvROK(sv) || (SvPOK(sv) && SvCUR(sv))
289 || (SvGMAGICAL(sv) && SvPOKp(sv) && SvCUR(sv))))
290 XSRETURN_UNDEF;
291
292 name = SvPV_nolen_const(ST(1));
293 rv = &PL_sv_undef;
294
295 if (SvROK(sv)) {
296 sv = MUTABLE_SV(SvRV(sv));
297 if (SvOBJECT(sv))
298 pkg = SvSTASH(sv);
299 }
300 else {
301 pkg = gv_stashsv(sv, 0);
302 }
303
304 if (pkg) {
305 GV * const gv = gv_fetchmethod_autoload(pkg, name, FALSE);
306 if (gv && isGV(gv))
307 rv = sv_2mortal(newRV(MUTABLE_SV(GvCV(gv))));
308 }
309
310 ST(0) = rv;
311 XSRETURN(1);
312}
313
314XS(XS_UNIVERSAL_DOES)
315{
316 dVAR;
317 dXSARGS;
318 PERL_UNUSED_ARG(cv);
319
320 if (items != 2)
321 Perl_croak(aTHX_ "Usage: invocant->DOES(kind)");
322 else {
323 SV * const sv = ST(0);
324 const char *name;
325
326 name = SvPV_nolen_const(ST(1));
327 if (sv_does( sv, name ))
328 XSRETURN_YES;
329
330 XSRETURN_NO;
331 }
332}
333
334XS(XS_UNIVERSAL_VERSION)
335{
336 dVAR;
337 dXSARGS;
338 HV *pkg;
339 GV **gvp;
340 GV *gv;
341 SV *sv;
342 const char *undef;
343 PERL_UNUSED_ARG(cv);
344
345 if (SvROK(ST(0))) {
346 sv = MUTABLE_SV(SvRV(ST(0)));
347 if (!SvOBJECT(sv))
348 Perl_croak(aTHX_ "Cannot find version of an unblessed reference");
349 pkg = SvSTASH(sv);
350 }
351 else {
352 pkg = gv_stashsv(ST(0), 0);
353 }
354
355 gvp = pkg ? (GV**)hv_fetchs(pkg, "VERSION", FALSE) : NULL;
356
357 if (gvp && isGV(gv = *gvp) && (sv = GvSV(gv)) && SvOK(sv)) {
358 SV * const nsv = sv_newmortal();
359 sv_setsv(nsv, sv);
360 sv = nsv;
361 if ( !sv_derived_from(sv, "version"))
362 upg_version(sv, FALSE);
363 undef = NULL;
364 }
365 else {
366 sv = &PL_sv_undef;
367 undef = "(undef)";
368 }
369
370 if (items > 1) {
371 SV *req = ST(1);
372
373 if (undef) {
374 if (pkg) {
375 const char * const name = HvNAME_get(pkg);
376 Perl_croak(aTHX_
377 "%s does not define $%s::VERSION--version check failed",
378 name, name);
379 } else {
380 Perl_croak(aTHX_
381 "%s defines neither package nor VERSION--version check failed",
382 SvPVx_nolen_const(ST(0)) );
383 }
384 }
385
386 if ( !sv_derived_from(req, "version")) {
387 /* req may very well be R/O, so create a new object */
388 req = sv_2mortal( new_version(req) );
389 }
390
391 if ( vcmp( req, sv ) > 0 ) {
392 if ( hv_exists(MUTABLE_HV(SvRV(req)), "qv", 2 ) ) {
393 Perl_croak(aTHX_ "%s version %"SVf" required--"
394 "this is only version %"SVf"", HvNAME_get(pkg),
395 SVfARG(sv_2mortal(vnormal(req))),
396 SVfARG(sv_2mortal(vnormal(sv))));
397 } else {
398 Perl_croak(aTHX_ "%s version %"SVf" required--"
399 "this is only version %"SVf"", HvNAME_get(pkg),
400 SVfARG(sv_2mortal(vstringify(req))),
401 SVfARG(sv_2mortal(vstringify(sv))));
402 }
403 }
404
405 }
406
407 if ( SvOK(sv) && sv_derived_from(sv, "version") ) {
408 ST(0) = sv_2mortal(vstringify(sv));
409 } else {
410 ST(0) = sv;
411 }
412
413 XSRETURN(1);
414}
415
416XS(XS_version_new)
417{
418 dVAR;
419 dXSARGS;
420 if (items > 3)
421 croak_xs_usage(cv, "class, version");
422 SP -= items;
423 {
424 SV *vs = ST(1);
425 SV *rv;
426 const char * const classname =
427 sv_isobject(ST(0)) /* get the class if called as an object method */
428 ? HvNAME(SvSTASH(SvRV(ST(0))))
429 : (char *)SvPV_nolen(ST(0));
430
431 if ( items == 1 || ! SvOK(vs) ) { /* no param or explicit undef */
432 /* create empty object */
433 vs = sv_newmortal();
434 sv_setpvs(vs, "0");
435 }
436 else if ( items == 3 ) {
437 vs = sv_newmortal();
438 Perl_sv_setpvf(aTHX_ vs,"v%s",SvPV_nolen_const(ST(2)));
439 }
440
441 rv = new_version(vs);
442 if ( strcmp(classname,"version") != 0 ) /* inherited new() */
443 sv_bless(rv, gv_stashpv(classname, GV_ADD));
444
445 mPUSHs(rv);
446 PUTBACK;
447 return;
448 }
449}
450
451XS(XS_version_stringify)
452{
453 dVAR;
454 dXSARGS;
455 if (items < 1)
456 croak_xs_usage(cv, "lobj, ...");
457 SP -= items;
458 {
459 SV * lobj = ST(0);
460
461 if (sv_derived_from(lobj, "version") && SvROK(lobj)) {
462 lobj = SvRV(lobj);
463 }
464 else
465 Perl_croak(aTHX_ "lobj is not of type version");
466
467 mPUSHs(vstringify(lobj));
468
469 PUTBACK;
470 return;
471 }
472}
473
474XS(XS_version_numify)
475{
476 dVAR;
477 dXSARGS;
478 if (items < 1)
479 croak_xs_usage(cv, "lobj, ...");
480 SP -= items;
481 {
482 SV * lobj = ST(0);
483
484 if (sv_derived_from(lobj, "version") && SvROK(lobj)) {
485 lobj = SvRV(lobj);
486 }
487 else
488 Perl_croak(aTHX_ "lobj is not of type version");
489
490 mPUSHs(vnumify(lobj));
491
492 PUTBACK;
493 return;
494 }
495}
496
497XS(XS_version_normal)
498{
499 dVAR;
500 dXSARGS;
501 if (items < 1)
502 croak_xs_usage(cv, "lobj, ...");
503 SP -= items;
504 {
505 SV * lobj = ST(0);
506
507 if (sv_derived_from(lobj, "version") && SvROK(lobj)) {
508 lobj = SvRV(lobj);
509 }
510 else
511 Perl_croak(aTHX_ "lobj is not of type version");
512
513 mPUSHs(vnormal(lobj));
514
515 PUTBACK;
516 return;
517 }
518}
519
520XS(XS_version_vcmp)
521{
522 dVAR;
523 dXSARGS;
524 if (items < 1)
525 croak_xs_usage(cv, "lobj, ...");
526 SP -= items;
527 {
528 SV * lobj = ST(0);
529
530 if (sv_derived_from(lobj, "version") && SvROK(lobj)) {
531 lobj = SvRV(lobj);
532 }
533 else
534 Perl_croak(aTHX_ "lobj is not of type version");
535
536 {
537 SV *rs;
538 SV *rvs;
539 SV * robj = ST(1);
540 const IV swap = (IV)SvIV(ST(2));
541
542 if ( ! sv_derived_from(robj, "version") )
543 {
544 robj = new_version(SvOK(robj) ? robj : newSVpvs_flags("0", SVs_TEMP));
545 sv_2mortal(robj);
546 }
547 rvs = SvRV(robj);
548
549 if ( swap )
550 {
551 rs = newSViv(vcmp(rvs,lobj));
552 }
553 else
554 {
555 rs = newSViv(vcmp(lobj,rvs));
556 }
557
558 mPUSHs(rs);
559 }
560
561 PUTBACK;
562 return;
563 }
564}
565
566XS(XS_version_boolean)
567{
568 dVAR;
569 dXSARGS;
570 if (items < 1)
571 croak_xs_usage(cv, "lobj, ...");
572 SP -= items;
573 if (sv_derived_from(ST(0), "version") && SvROK(ST(0))) {
574 SV * const lobj = SvRV(ST(0));
575 SV * const rs = newSViv( vcmp(lobj,new_version(newSVpvs("0"))) );
576 mPUSHs(rs);
577 PUTBACK;
578 return;
579 }
580 else
581 Perl_croak(aTHX_ "lobj is not of type version");
582}
583
584XS(XS_version_noop)
585{
586 dVAR;
587 dXSARGS;
588 if (items < 1)
589 croak_xs_usage(cv, "lobj, ...");
590 if (sv_derived_from(ST(0), "version") && SvROK(ST(0)))
591 Perl_croak(aTHX_ "operation not supported with version object");
592 else
593 Perl_croak(aTHX_ "lobj is not of type version");
594#ifndef HASATTRIBUTE_NORETURN
595 XSRETURN_EMPTY;
596#endif
597}
598
599XS(XS_version_is_alpha)
600{
601 dVAR;
602 dXSARGS;
603 if (items != 1)
604 croak_xs_usage(cv, "lobj");
605 SP -= items;
606 if (sv_derived_from(ST(0), "version") && SvROK(ST(0))) {
607 SV * const lobj = ST(0);
608 if ( hv_exists(MUTABLE_HV(SvRV(lobj)), "alpha", 5 ) )
609 XSRETURN_YES;
610 else
611 XSRETURN_NO;
612 PUTBACK;
613 return;
614 }
615 else
616 Perl_croak(aTHX_ "lobj is not of type version");
617}
618
619XS(XS_version_qv)
620{
621 dVAR;
622 dXSARGS;
623 PERL_UNUSED_ARG(cv);
624 SP -= items;
625 {
626 SV * ver = ST(0);
627 SV * rv;
628 const char * classname = "";
629 if ( items == 2 && SvOK(ST(1)) ) {
630 /* getting called as object or class method */
631 ver = ST(1);
632 classname =
633 sv_isobject(ST(0)) /* class called as an object method */
634 ? HvNAME_get(SvSTASH(SvRV(ST(0))))
635 : (char *)SvPV_nolen(ST(0));
636 }
637 if ( !SvVOK(ver) ) { /* not already a v-string */
638 rv = sv_newmortal();
639 sv_setsv(rv,ver); /* make a duplicate */
640 upg_version(rv, TRUE);
641 } else {
642 rv = sv_2mortal(new_version(ver));
643 }
644 if ( items == 2 && strcmp(classname,"version") ) { /* inherited new() */
645 sv_bless(rv, gv_stashpv(classname, GV_ADD));
646 }
647 PUSHs(rv);
648 }
649 PUTBACK;
650 return;
651}
652
653XS(XS_version_is_qv)
654{
655 dVAR;
656 dXSARGS;
657 if (items != 1)
658 croak_xs_usage(cv, "lobj");
659 SP -= items;
660 if (sv_derived_from(ST(0), "version") && SvROK(ST(0))) {
661 SV * const lobj = ST(0);
662 if ( hv_exists(MUTABLE_HV(SvRV(lobj)), "qv", 2 ) )
663 XSRETURN_YES;
664 else
665 XSRETURN_NO;
666 PUTBACK;
667 return;
668 }
669 else
670 Perl_croak(aTHX_ "lobj is not of type version");
671}
672
673XS(XS_utf8_is_utf8)
674{
675 dVAR;
676 dXSARGS;
677 if (items != 1)
678 croak_xs_usage(cv, "sv");
679 else {
680 SV * const sv = ST(0);
681 SvGETMAGIC(sv);
682 if (SvUTF8(sv))
683 XSRETURN_YES;
684 else
685 XSRETURN_NO;
686 }
687 XSRETURN_EMPTY;
688}
689
690XS(XS_utf8_valid)
691{
692 dVAR;
693 dXSARGS;
694 if (items != 1)
695 croak_xs_usage(cv, "sv");
696 else {
697 SV * const sv = ST(0);
698 STRLEN len;
699 const char * const s = SvPV_const(sv,len);
700 if (!SvUTF8(sv) || is_utf8_string((const U8*)s,len))
701 XSRETURN_YES;
702 else
703 XSRETURN_NO;
704 }
705 XSRETURN_EMPTY;
706}
707
708XS(XS_utf8_encode)
709{
710 dVAR;
711 dXSARGS;
712 if (items != 1)
713 croak_xs_usage(cv, "sv");
714 sv_utf8_encode(ST(0));
715 XSRETURN_EMPTY;
716}
717
718XS(XS_utf8_decode)
719{
720 dVAR;
721 dXSARGS;
722 if (items != 1)
723 croak_xs_usage(cv, "sv");
724 else {
725 SV * const sv = ST(0);
726 const bool RETVAL = sv_utf8_decode(sv);
727 ST(0) = boolSV(RETVAL);
728 sv_2mortal(ST(0));
729 }
730 XSRETURN(1);
731}
732
733XS(XS_utf8_upgrade)
734{
735 dVAR;
736 dXSARGS;
737 if (items != 1)
738 croak_xs_usage(cv, "sv");
739 else {
740 SV * const sv = ST(0);
741 STRLEN RETVAL;
742 dXSTARG;
743
744 RETVAL = sv_utf8_upgrade(sv);
745 XSprePUSH; PUSHi((IV)RETVAL);
746 }
747 XSRETURN(1);
748}
749
750XS(XS_utf8_downgrade)
751{
752 dVAR;
753 dXSARGS;
754 if (items < 1 || items > 2)
755 croak_xs_usage(cv, "sv, failok=0");
756 else {
757 SV * const sv = ST(0);
758 const bool failok = (items < 2) ? 0 : (int)SvIV(ST(1));
759 const bool RETVAL = sv_utf8_downgrade(sv, failok);
760
761 ST(0) = boolSV(RETVAL);
762 sv_2mortal(ST(0));
763 }
764 XSRETURN(1);
765}
766
767XS(XS_utf8_native_to_unicode)
768{
769 dVAR;
770 dXSARGS;
771 const UV uv = SvUV(ST(0));
772
773 if (items > 1)
774 croak_xs_usage(cv, "sv");
775
776 ST(0) = sv_2mortal(newSViv(NATIVE_TO_UNI(uv)));
777 XSRETURN(1);
778}
779
780XS(XS_utf8_unicode_to_native)
781{
782 dVAR;
783 dXSARGS;
784 const UV uv = SvUV(ST(0));
785
786 if (items > 1)
787 croak_xs_usage(cv, "sv");
788
789 ST(0) = sv_2mortal(newSViv(UNI_TO_NATIVE(uv)));
790 XSRETURN(1);
791}
792
793XS(XS_Internals_SvREADONLY) /* This is dangerous stuff. */
794{
795 dVAR;
796 dXSARGS;
797 SV * const sv = SvRV(ST(0));
798 PERL_UNUSED_ARG(cv);
799
800 if (items == 1) {
801 if (SvREADONLY(sv))
802 XSRETURN_YES;
803 else
804 XSRETURN_NO;
805 }
806 else if (items == 2) {
807 if (SvTRUE(ST(1))) {
808 SvREADONLY_on(sv);
809 XSRETURN_YES;
810 }
811 else {
812 /* I hope you really know what you are doing. */
813 SvREADONLY_off(sv);
814 XSRETURN_NO;
815 }
816 }
817 XSRETURN_UNDEF; /* Can't happen. */
818}
819
820XS(XS_Internals_SvREFCNT) /* This is dangerous stuff. */
821{
822 dVAR;
823 dXSARGS;
824 SV * const sv = SvRV(ST(0));
825 PERL_UNUSED_ARG(cv);
826
827 if (items == 1)
828 XSRETURN_IV(SvREFCNT(sv) - 1); /* Minus the ref created for us. */
829 else if (items == 2) {
830 /* I hope you really know what you are doing. */
831 SvREFCNT(sv) = SvIV(ST(1));
832 XSRETURN_IV(SvREFCNT(sv));
833 }
834 XSRETURN_UNDEF; /* Can't happen. */
835}
836
837XS(XS_Internals_hv_clear_placehold)
838{
839 dVAR;
840 dXSARGS;
841
842 if (items != 1)
843 croak_xs_usage(cv, "hv");
844 else {
845 HV * const hv = MUTABLE_HV(SvRV(ST(0)));
846 hv_clear_placeholders(hv);
847 XSRETURN(0);
848 }
849}
850
851XS(XS_PerlIO_get_layers)
852{
853 dVAR;
854 dXSARGS;
855 if (items < 1 || items % 2 == 0)
856 croak_xs_usage(cv, "filehandle[,args]");
857#ifdef USE_PERLIO
858 {
859 SV * sv;
860 GV * gv;
861 IO * io;
862 bool input = TRUE;
863 bool details = FALSE;
864
865 if (items > 1) {
866 SV * const *svp;
867 for (svp = MARK + 2; svp <= SP; svp += 2) {
868 SV * const * const varp = svp;
869 SV * const * const valp = svp + 1;
870 STRLEN klen;
871 const char * const key = SvPV_const(*varp, klen);
872
873 switch (*key) {
874 case 'i':
875 if (klen == 5 && memEQ(key, "input", 5)) {
876 input = SvTRUE(*valp);
877 break;
878 }
879 goto fail;
880 case 'o':
881 if (klen == 6 && memEQ(key, "output", 6)) {
882 input = !SvTRUE(*valp);
883 break;
884 }
885 goto fail;
886 case 'd':
887 if (klen == 7 && memEQ(key, "details", 7)) {
888 details = SvTRUE(*valp);
889 break;
890 }
891 goto fail;
892 default:
893 fail:
894 Perl_croak(aTHX_
895 "get_layers: unknown argument '%s'",
896 key);
897 }
898 }
899
900 SP -= (items - 1);
901 }
902
903 sv = POPs;
904 gv = MUTABLE_GV(sv);
905
906 if (!isGV(sv)) {
907 if (SvROK(sv) && isGV(SvRV(sv)))
908 gv = MUTABLE_GV(SvRV(sv));
909 else if (SvPOKp(sv))
910 gv = gv_fetchsv(sv, 0, SVt_PVIO);
911 }
912
913 if (gv && (io = GvIO(gv))) {
914 AV* const av = PerlIO_get_layers(aTHX_ input ?
915 IoIFP(io) : IoOFP(io));
916 I32 i;
917 const I32 last = av_len(av);
918 I32 nitem = 0;
919
920 for (i = last; i >= 0; i -= 3) {
921 SV * const * const namsvp = av_fetch(av, i - 2, FALSE);
922 SV * const * const argsvp = av_fetch(av, i - 1, FALSE);
923 SV * const * const flgsvp = av_fetch(av, i, FALSE);
924
925 const bool namok = namsvp && *namsvp && SvPOK(*namsvp);
926 const bool argok = argsvp && *argsvp && SvPOK(*argsvp);
927 const bool flgok = flgsvp && *flgsvp && SvIOK(*flgsvp);
928
929 if (details) {
930 /* Indents of 5? Yuck. */
931 /* We know that PerlIO_get_layers creates a new SV for
932 the name and flags, so we can just take a reference
933 and "steal" it when we free the AV below. */
934 XPUSHs(namok
935 ? sv_2mortal(SvREFCNT_inc_simple_NN(*namsvp))
936 : &PL_sv_undef);
937 XPUSHs(argok
938 ? newSVpvn_flags(SvPVX_const(*argsvp),
939 SvCUR(*argsvp),
940 (SvUTF8(*argsvp) ? SVf_UTF8 : 0)
941 | SVs_TEMP)
942 : &PL_sv_undef);
943 XPUSHs(flgok
944 ? sv_2mortal(SvREFCNT_inc_simple_NN(*flgsvp))
945 : &PL_sv_undef);
946 nitem += 3;
947 }
948 else {
949 if (namok && argok)
950 XPUSHs(sv_2mortal(Perl_newSVpvf(aTHX_ "%"SVf"(%"SVf")",
951 SVfARG(*namsvp),
952 SVfARG(*argsvp))));
953 else if (namok)
954 XPUSHs(sv_2mortal(SvREFCNT_inc_simple_NN(*namsvp)));
955 else
956 XPUSHs(&PL_sv_undef);
957 nitem++;
958 if (flgok) {
959 const IV flags = SvIVX(*flgsvp);
960
961 if (flags & PERLIO_F_UTF8) {
962 XPUSHs(newSVpvs_flags("utf8", SVs_TEMP));
963 nitem++;
964 }
965 }
966 }
967 }
968
969 SvREFCNT_dec(av);
970
971 XSRETURN(nitem);
972 }
973 }
974#endif
975
976 XSRETURN(0);
977}
978
979XS(XS_Internals_hash_seed)
980{
981 dVAR;
982 /* Using dXSARGS would also have dITEM and dSP,
983 * which define 2 unused local variables. */
984 dAXMARK;
985 PERL_UNUSED_ARG(cv);
986 PERL_UNUSED_VAR(mark);
987 XSRETURN_UV(PERL_HASH_SEED);
988}
989
990XS(XS_Internals_rehash_seed)
991{
992 dVAR;
993 /* Using dXSARGS would also have dITEM and dSP,
994 * which define 2 unused local variables. */
995 dAXMARK;
996 PERL_UNUSED_ARG(cv);
997 PERL_UNUSED_VAR(mark);
998 XSRETURN_UV(PL_rehash_seed);
999}
1000
1001XS(XS_Internals_HvREHASH) /* Subject to change */
1002{
1003 dVAR;
1004 dXSARGS;
1005 PERL_UNUSED_ARG(cv);
1006 if (SvROK(ST(0))) {
1007 const HV * const hv = (const HV *) SvRV(ST(0));
1008 if (items == 1 && SvTYPE(hv) == SVt_PVHV) {
1009 if (HvREHASH(hv))
1010 XSRETURN_YES;
1011 else
1012 XSRETURN_NO;
1013 }
1014 }
1015 Perl_croak(aTHX_ "Internals::HvREHASH $hashref");
1016}
1017
1018XS(XS_re_is_regexp)
1019{
1020 dVAR;
1021 dXSARGS;
1022 PERL_UNUSED_VAR(cv);
1023
1024 if (items != 1)
1025 croak_xs_usage(cv, "sv");
1026
1027 SP -= items;
1028
1029 if (SvRXOK(ST(0))) {
1030 XSRETURN_YES;
1031 } else {
1032 XSRETURN_NO;
1033 }
1034}
1035
1036XS(XS_re_regnames_count)
1037{
1038 REGEXP *rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1039 SV * ret;
1040 dVAR;
1041 dXSARGS;
1042
1043 if (items != 0)
1044 croak_xs_usage(cv, "");
1045
1046 SP -= items;
1047
1048 if (!rx)
1049 XSRETURN_UNDEF;
1050
1051 ret = CALLREG_NAMED_BUFF_COUNT(rx);
1052
1053 SPAGAIN;
1054
1055 if (ret) {
1056 mXPUSHs(ret);
1057 PUTBACK;
1058 return;
1059 } else {
1060 XSRETURN_UNDEF;
1061 }
1062}
1063
1064XS(XS_re_regname)
1065{
1066 dVAR;
1067 dXSARGS;
1068 REGEXP * rx;
1069 U32 flags;
1070 SV * ret;
1071
1072 if (items < 1 || items > 2)
1073 croak_xs_usage(cv, "name[, all ]");
1074
1075 SP -= items;
1076
1077 rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1078
1079 if (!rx)
1080 XSRETURN_UNDEF;
1081
1082 if (items == 2 && SvTRUE(ST(1))) {
1083 flags = RXapif_ALL;
1084 } else {
1085 flags = RXapif_ONE;
1086 }
1087 ret = CALLREG_NAMED_BUFF_FETCH(rx, ST(0), (flags | RXapif_REGNAME));
1088
1089 if (ret) {
1090 mXPUSHs(ret);
1091 XSRETURN(1);
1092 }
1093 XSRETURN_UNDEF;
1094}
1095
1096
1097XS(XS_re_regnames)
1098{
1099 dVAR;
1100 dXSARGS;
1101 REGEXP * rx;
1102 U32 flags;
1103 SV *ret;
1104 AV *av;
1105 I32 length;
1106 I32 i;
1107 SV **entry;
1108
1109 if (items > 1)
1110 croak_xs_usage(cv, "[all]");
1111
1112 rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1113
1114 if (!rx)
1115 XSRETURN_UNDEF;
1116
1117 if (items == 1 && SvTRUE(ST(0))) {
1118 flags = RXapif_ALL;
1119 } else {
1120 flags = RXapif_ONE;
1121 }
1122
1123 SP -= items;
1124
1125 ret = CALLREG_NAMED_BUFF_ALL(rx, (flags | RXapif_REGNAMES));
1126
1127 SPAGAIN;
1128
1129 SP -= items;
1130
1131 if (!ret)
1132 XSRETURN_UNDEF;
1133
1134 av = MUTABLE_AV(SvRV(ret));
1135 length = av_len(av);
1136
1137 for (i = 0; i <= length; i++) {
1138 entry = av_fetch(av, i, FALSE);
1139
1140 if (!entry)
1141 Perl_croak(aTHX_ "NULL array element in re::regnames()");
1142
1143 mXPUSHs(SvREFCNT_inc_simple_NN(*entry));
1144 }
1145
1146 SvREFCNT_dec(ret);
1147
1148 PUTBACK;
1149 return;
1150}
1151
1152XS(XS_re_regexp_pattern)
1153{
1154 dVAR;
1155 dXSARGS;
1156 REGEXP *re;
1157
1158 if (items != 1)
1159 croak_xs_usage(cv, "sv");
1160
1161 SP -= items;
1162
1163 /*
1164 Checks if a reference is a regex or not. If the parameter is
1165 not a ref, or is not the result of a qr// then returns false
1166 in scalar context and an empty list in list context.
1167 Otherwise in list context it returns the pattern and the
1168 modifiers, in scalar context it returns the pattern just as it
1169 would if the qr// was stringified normally, regardless as
1170 to the class of the variable and any strigification overloads
1171 on the object.
1172 */
1173
1174 if ((re = SvRX(ST(0)))) /* assign deliberate */
1175 {
1176 /* Houston, we have a regex! */
1177 SV *pattern;
1178 STRLEN left = 0;
1179 char reflags[sizeof(INT_PAT_MODS)];
1180
1181 if ( GIMME_V == G_ARRAY ) {
1182 /*
1183 we are in list context so stringify
1184 the modifiers that apply. We ignore "negative
1185 modifiers" in this scenario.
1186 */
1187
1188 const char *fptr = INT_PAT_MODS;
1189 char ch;
1190 U16 match_flags = (U16)((RX_EXTFLAGS(re) & PMf_COMPILETIME)
1191 >> RXf_PMf_STD_PMMOD_SHIFT);
1192
1193 while((ch = *fptr++)) {
1194 if(match_flags & 1) {
1195 reflags[left++] = ch;
1196 }
1197 match_flags >>= 1;
1198 }
1199
1200 pattern = newSVpvn_flags(RX_PRECOMP(re),RX_PRELEN(re),
1201 (RX_UTF8(re) ? SVf_UTF8 : 0) | SVs_TEMP);
1202
1203 /* return the pattern and the modifiers */
1204 XPUSHs(pattern);
1205 XPUSHs(newSVpvn_flags(reflags, left, SVs_TEMP));
1206 XSRETURN(2);
1207 } else {
1208 /* Scalar, so use the string that Perl would return */
1209 /* return the pattern in (?msix:..) format */
1210#if PERL_VERSION >= 11
1211 pattern = sv_2mortal(newSVsv(MUTABLE_SV(re)));
1212#else
1213 pattern = newSVpvn_flags(RX_WRAPPED(re), RX_WRAPLEN(re),
1214 (RX_UTF8(re) ? SVf_UTF8 : 0) | SVs_TEMP);
1215#endif
1216 XPUSHs(pattern);
1217 XSRETURN(1);
1218 }
1219 } else {
1220 /* It ain't a regexp folks */
1221 if ( GIMME_V == G_ARRAY ) {
1222 /* return the empty list */
1223 XSRETURN_UNDEF;
1224 } else {
1225 /* Because of the (?:..) wrapping involved in a
1226 stringified pattern it is impossible to get a
1227 result for a real regexp that would evaluate to
1228 false. Therefore we can return PL_sv_no to signify
1229 that the object is not a regex, this means that one
1230 can say
1231
1232 if (regex($might_be_a_regex) eq '(?:foo)') { }
1233
1234 and not worry about undefined values.
1235 */
1236 XSRETURN_NO;
1237 }
1238 }
1239 /* NOT-REACHED */
1240}
1241
1242XS(XS_Tie_Hash_NamedCapture_FETCH)
1243{
1244 dVAR;
1245 dXSARGS;
1246 REGEXP * rx;
1247 U32 flags;
1248 SV * ret;
1249
1250 if (items != 2)
1251 croak_xs_usage(cv, "$key, $flags");
1252
1253 rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1254
1255 if (!rx || !SvROK(ST(0)))
1256 XSRETURN_UNDEF;
1257
1258 SP -= items;
1259
1260 flags = (U32)INT2PTR(IV,SvIV(SvRV(MUTABLE_SV(ST(0)))));
1261 ret = CALLREG_NAMED_BUFF_FETCH(rx, ST(1), flags);
1262
1263 SPAGAIN;
1264
1265 if (ret) {
1266 mXPUSHs(ret);
1267 PUTBACK;
1268 return;
1269 }
1270 XSRETURN_UNDEF;
1271}
1272
1273XS(XS_Tie_Hash_NamedCapture_STORE)
1274{
1275 dVAR;
1276 dXSARGS;
1277 REGEXP * rx;
1278 U32 flags;
1279
1280 if (items != 3)
1281 croak_xs_usage(cv, "$key, $value, $flags");
1282
1283 rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1284
1285 if (!rx || !SvROK(ST(0))) {
1286 if (!PL_localizing)
1287 Perl_croak_no_modify(aTHX);
1288 else
1289 XSRETURN_UNDEF;
1290 }
1291
1292 SP -= items;
1293
1294 flags = (U32)INT2PTR(IV,SvIV(SvRV(MUTABLE_SV(ST(0)))));
1295 CALLREG_NAMED_BUFF_STORE(rx,ST(1), ST(2), flags);
1296}
1297
1298XS(XS_Tie_Hash_NamedCapture_DELETE)
1299{
1300 dVAR;
1301 dXSARGS;
1302 REGEXP * rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1303 U32 flags;
1304
1305 if (items != 2)
1306 croak_xs_usage(cv, "$key, $flags");
1307
1308 if (!rx || !SvROK(ST(0)))
1309 Perl_croak_no_modify(aTHX);
1310
1311 SP -= items;
1312
1313 flags = (U32)INT2PTR(IV,SvIV(SvRV(MUTABLE_SV(ST(0)))));
1314 CALLREG_NAMED_BUFF_DELETE(rx, ST(1), flags);
1315}
1316
1317XS(XS_Tie_Hash_NamedCapture_CLEAR)
1318{
1319 dVAR;
1320 dXSARGS;
1321 REGEXP * rx;
1322 U32 flags;
1323
1324 if (items != 1)
1325 croak_xs_usage(cv, "$flags");
1326
1327 rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1328
1329 if (!rx || !SvROK(ST(0)))
1330 Perl_croak_no_modify(aTHX);
1331
1332 SP -= items;
1333
1334 flags = (U32)INT2PTR(IV,SvIV(SvRV(MUTABLE_SV(ST(0)))));
1335 CALLREG_NAMED_BUFF_CLEAR(rx, flags);
1336}
1337
1338XS(XS_Tie_Hash_NamedCapture_EXISTS)
1339{
1340 dVAR;
1341 dXSARGS;
1342 REGEXP * rx;
1343 U32 flags;
1344 SV * ret;
1345
1346 if (items != 2)
1347 croak_xs_usage(cv, "$key, $flags");
1348
1349 rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1350
1351 if (!rx || !SvROK(ST(0)))
1352 XSRETURN_UNDEF;
1353
1354 SP -= items;
1355
1356 flags = (U32)INT2PTR(IV,SvIV(SvRV(MUTABLE_SV(ST(0)))));
1357 ret = CALLREG_NAMED_BUFF_EXISTS(rx, ST(1), flags);
1358
1359 SPAGAIN;
1360
1361 XPUSHs(ret);
1362 PUTBACK;
1363 return;
1364}
1365
1366XS(XS_Tie_Hash_NamedCapture_FIRSTK)
1367{
1368 dVAR;
1369 dXSARGS;
1370 REGEXP * rx;
1371 U32 flags;
1372 SV * ret;
1373
1374 if (items != 1)
1375 croak_xs_usage(cv, "");
1376
1377 rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1378
1379 if (!rx || !SvROK(ST(0)))
1380 XSRETURN_UNDEF;
1381
1382 SP -= items;
1383
1384 flags = (U32)INT2PTR(IV,SvIV(SvRV(MUTABLE_SV(ST(0)))));
1385 ret = CALLREG_NAMED_BUFF_FIRSTKEY(rx, flags);
1386
1387 SPAGAIN;
1388
1389 if (ret) {
1390 mXPUSHs(ret);
1391 PUTBACK;
1392 } else {
1393 XSRETURN_UNDEF;
1394 }
1395
1396}
1397
1398XS(XS_Tie_Hash_NamedCapture_NEXTK)
1399{
1400 dVAR;
1401 dXSARGS;
1402 REGEXP * rx;
1403 U32 flags;
1404 SV * ret;
1405
1406 if (items != 2)
1407 croak_xs_usage(cv, "$lastkey");
1408
1409 rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1410
1411 if (!rx || !SvROK(ST(0)))
1412 XSRETURN_UNDEF;
1413
1414 SP -= items;
1415
1416 flags = (U32)INT2PTR(IV,SvIV(SvRV(MUTABLE_SV(ST(0)))));
1417 ret = CALLREG_NAMED_BUFF_NEXTKEY(rx, ST(1), flags);
1418
1419 SPAGAIN;
1420
1421 if (ret) {
1422 mXPUSHs(ret);
1423 } else {
1424 XSRETURN_UNDEF;
1425 }
1426 PUTBACK;
1427}
1428
1429XS(XS_Tie_Hash_NamedCapture_SCALAR)
1430{
1431 dVAR;
1432 dXSARGS;
1433 REGEXP * rx;
1434 U32 flags;
1435 SV * ret;
1436
1437 if (items != 1)
1438 croak_xs_usage(cv, "");
1439
1440 rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1441
1442 if (!rx || !SvROK(ST(0)))
1443 XSRETURN_UNDEF;
1444
1445 SP -= items;
1446
1447 flags = (U32)INT2PTR(IV,SvIV(SvRV(MUTABLE_SV(ST(0)))));
1448 ret = CALLREG_NAMED_BUFF_SCALAR(rx, flags);
1449
1450 SPAGAIN;
1451
1452 if (ret) {
1453 mXPUSHs(ret);
1454 PUTBACK;
1455 return;
1456 } else {
1457 XSRETURN_UNDEF;
1458 }
1459}
1460
1461XS(XS_Tie_Hash_NamedCapture_flags)
1462{
1463 dVAR;
1464 dXSARGS;
1465
1466 if (items != 0)
1467 croak_xs_usage(cv, "");
1468
1469 mXPUSHu(RXapif_ONE);
1470 mXPUSHu(RXapif_ALL);
1471 PUTBACK;
1472 return;
1473}
1474
1475struct xsub_details {
1476 const char *name;
1477 XSUBADDR_t xsub;
1478 const char *proto;
1479};
1480
1481struct xsub_details details[] = {
1482 {"UNIVERSAL::isa", XS_UNIVERSAL_isa, NULL},
1483 {"UNIVERSAL::can", XS_UNIVERSAL_can, NULL},
1484 {"UNIVERSAL::DOES", XS_UNIVERSAL_DOES, NULL},
1485 {"UNIVERSAL::VERSION", XS_UNIVERSAL_VERSION, NULL},
1486 {"version::()", XS_version_noop, NULL},
1487 {"version::new", XS_version_new, NULL},
1488 {"version::parse", XS_version_new, NULL},
1489 {"version::(\"\"", XS_version_stringify, NULL},
1490 {"version::stringify", XS_version_stringify, NULL},
1491 {"version::(0+", XS_version_numify, NULL},
1492 {"version::numify", XS_version_numify, NULL},
1493 {"version::normal", XS_version_normal, NULL},
1494 {"version::(cmp", XS_version_vcmp, NULL},
1495 {"version::(<=>", XS_version_vcmp, NULL},
1496 {"version::vcmp", XS_version_vcmp, NULL},
1497 {"version::(bool", XS_version_boolean, NULL},
1498 {"version::boolean", XS_version_boolean, NULL},
1499 {"version::(nomethod", XS_version_noop, NULL},
1500 {"version::noop", XS_version_noop, NULL},
1501 {"version::is_alpha", XS_version_is_alpha, NULL},
1502 {"version::qv", XS_version_qv, NULL},
1503 {"version::declare", XS_version_qv, NULL},
1504 {"version::is_qv", XS_version_is_qv, NULL},
1505 {"utf8::is_utf8", XS_utf8_is_utf8, NULL},
1506 {"utf8::valid", XS_utf8_valid, NULL},
1507 {"utf8::encode", XS_utf8_encode, NULL},
1508 {"utf8::decode", XS_utf8_decode, NULL},
1509 {"utf8::upgrade", XS_utf8_upgrade, NULL},
1510 {"utf8::downgrade", XS_utf8_downgrade, NULL},
1511 {"utf8::native_to_unicode", XS_utf8_native_to_unicode, NULL},
1512 {"utf8::unicode_to_native", XS_utf8_unicode_to_native, NULL},
1513 {"Internals::SvREADONLY", XS_Internals_SvREADONLY, "\\[$%@];$"},
1514 {"Internals::SvREFCNT", XS_Internals_SvREFCNT, "\\[$%@];$"},
1515 {"Internals::hv_clear_placeholders", XS_Internals_hv_clear_placehold, "\\%"},
1516 {"PerlIO::get_layers", XS_PerlIO_get_layers, "*;@"},
1517 {"Internals::hash_seed", XS_Internals_hash_seed, ""},
1518 {"Internals::rehash_seed", XS_Internals_rehash_seed, ""},
1519 {"Internals::HvREHASH", XS_Internals_HvREHASH, "\\%"},
1520 {"re::is_regexp", XS_re_is_regexp, "$"},
1521 {"re::regname", XS_re_regname, ";$$"},
1522 {"re::regnames", XS_re_regnames, ";$"},
1523 {"re::regnames_count", XS_re_regnames_count, ""},
1524 {"re::regexp_pattern", XS_re_regexp_pattern, "$"},
1525 {"Tie::Hash::NamedCapture::FETCH", XS_Tie_Hash_NamedCapture_FETCH, NULL},
1526 {"Tie::Hash::NamedCapture::STORE", XS_Tie_Hash_NamedCapture_STORE, NULL},
1527 {"Tie::Hash::NamedCapture::DELETE", XS_Tie_Hash_NamedCapture_DELETE, NULL},
1528 {"Tie::Hash::NamedCapture::CLEAR", XS_Tie_Hash_NamedCapture_CLEAR, NULL},
1529 {"Tie::Hash::NamedCapture::EXISTS", XS_Tie_Hash_NamedCapture_EXISTS, NULL},
1530 {"Tie::Hash::NamedCapture::FIRSTKEY", XS_Tie_Hash_NamedCapture_FIRSTK, NULL},
1531 {"Tie::Hash::NamedCapture::NEXTKEY", XS_Tie_Hash_NamedCapture_NEXTK, NULL},
1532 {"Tie::Hash::NamedCapture::SCALAR", XS_Tie_Hash_NamedCapture_SCALAR, NULL},
1533 {"Tie::Hash::NamedCapture::flags", XS_Tie_Hash_NamedCapture_flags, NULL}
1534};
1535
1536void
1537Perl_boot_core_UNIVERSAL(pTHX)
1538{
1539 dVAR;
1540 static const char file[] = __FILE__;
1541 struct xsub_details *xsub = details;
1542 const struct xsub_details *end
1543 = details + sizeof(details) / sizeof(details[0]);
1544
1545 do {
1546 newXS_flags(xsub->name, xsub->xsub, file, xsub->proto, 0);
1547 } while (++xsub < end);
1548
1549 /* register the overloading (type 'A') magic */
1550 PL_amagic_generation++;
1551
1552 /* Providing a Regexp::DESTROY fixes #21347. See test in t/op/ref.t */
1553 CvFILE(newCONSTSUB(get_hv("Regexp::", GV_ADD), "DESTROY", NULL))
1554 = (char *)file;
1555}
1556
1557/*
1558 * Local variables:
1559 * c-indentation-style: bsd
1560 * c-basic-offset: 4
1561 * indent-tabs-mode: t
1562 * End:
1563 *
1564 * ex: set ts=8 sts=4 sw=4 noet:
1565 */