This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
ext/mro: use memEQs() for constant string checks
[perl5.git] / universal.c
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 separate 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 #if defined(USE_PERLIO)
33 #include "perliol.h" /* For the PERLIO_F_XXX */
34 #endif
35
36 /*
37  * Contributed by Graham Barr  <Graham.Barr@tiuk.ti.com>
38  * The main guts of traverse_isa was actually copied from gv_fetchmeth
39  */
40
41 STATIC bool
42 S_isa_lookup(pTHX_ HV *stash, const char * const name, STRLEN len, U32 flags)
43 {
44     const struct mro_meta *const meta = HvMROMETA(stash);
45     HV *isa = meta->isa;
46     const HV *our_stash;
47
48     PERL_ARGS_ASSERT_ISA_LOOKUP;
49
50     if (!isa) {
51         (void)mro_get_linear_isa(stash);
52         isa = meta->isa;
53     }
54
55     if (hv_common(isa, NULL, name, len, ( flags & SVf_UTF8 ? HVhek_UTF8 : 0),
56                   HV_FETCH_ISEXISTS, NULL, 0)) {
57         /* Direct name lookup worked.  */
58         return TRUE;
59     }
60
61     /* A stash/class can go by many names (ie. User == main::User), so 
62        we use the HvENAME in the stash itself, which is canonical, falling
63        back to HvNAME if necessary.  */
64     our_stash = gv_stashpvn(name, len, flags);
65
66     if (our_stash) {
67         HEK *canon_name = HvENAME_HEK(our_stash);
68         if (!canon_name) canon_name = HvNAME_HEK(our_stash);
69         assert(canon_name);
70         if (hv_common(isa, NULL, HEK_KEY(canon_name), HEK_LEN(canon_name),
71                       HEK_FLAGS(canon_name),
72                       HV_FETCH_ISEXISTS, NULL, HEK_HASH(canon_name))) {
73             return TRUE;
74         }
75     }
76
77     return FALSE;
78 }
79
80 /*
81 =head1 SV Manipulation Functions
82
83 =for apidoc sv_derived_from_pvn
84
85 Returns a boolean indicating whether the SV is derived from the specified class
86 I<at the C level>.  To check derivation at the Perl level, call C<isa()> as a
87 normal Perl method.
88
89 Currently, the only significant value for C<flags> is SVf_UTF8.
90
91 =cut
92
93 =for apidoc sv_derived_from_sv
94
95 Exactly like L</sv_derived_from_pvn>, but takes the name string in the form
96 of an SV instead of a string/length pair.
97
98 =cut
99
100 */
101
102 bool
103 Perl_sv_derived_from_sv(pTHX_ SV *sv, SV *namesv, U32 flags)
104 {
105     char *namepv;
106     STRLEN namelen;
107     PERL_ARGS_ASSERT_SV_DERIVED_FROM_SV;
108     namepv = SvPV(namesv, namelen);
109     if (SvUTF8(namesv))
110        flags |= SVf_UTF8;
111     return sv_derived_from_pvn(sv, namepv, namelen, flags);
112 }
113
114 /*
115 =for apidoc sv_derived_from
116
117 Exactly like L</sv_derived_from_pv>, but doesn't take a C<flags> parameter.
118
119 =cut
120 */
121
122 bool
123 Perl_sv_derived_from(pTHX_ SV *sv, const char *const name)
124 {
125     PERL_ARGS_ASSERT_SV_DERIVED_FROM;
126     return sv_derived_from_pvn(sv, name, strlen(name), 0);
127 }
128
129 /*
130 =for apidoc sv_derived_from_pv
131
132 Exactly like L</sv_derived_from_pvn>, but takes a nul-terminated string 
133 instead of a string/length pair.
134
135 =cut
136 */
137
138
139 bool
140 Perl_sv_derived_from_pv(pTHX_ SV *sv, const char *const name, U32 flags)
141 {
142     PERL_ARGS_ASSERT_SV_DERIVED_FROM_PV;
143     return sv_derived_from_pvn(sv, name, strlen(name), flags);
144 }
145
146 bool
147 Perl_sv_derived_from_pvn(pTHX_ SV *sv, const char *const name, const STRLEN len, U32 flags)
148 {
149     HV *stash;
150
151     PERL_ARGS_ASSERT_SV_DERIVED_FROM_PVN;
152
153     SvGETMAGIC(sv);
154
155     if (SvROK(sv)) {
156         const char *type;
157         sv = SvRV(sv);
158         type = sv_reftype(sv,0);
159         if (type && strEQ(type,name))
160             return TRUE;
161         if (!SvOBJECT(sv))
162             return FALSE;
163         stash = SvSTASH(sv);
164     }
165     else {
166         stash = gv_stashsv(sv, 0);
167     }
168
169     if (stash && isa_lookup(stash, name, len, flags))
170         return TRUE;
171
172     stash = gv_stashpvs("UNIVERSAL", 0);
173     return stash && isa_lookup(stash, name, len, flags);
174 }
175
176 /*
177 =for apidoc sv_does_sv
178
179 Returns a boolean indicating whether the SV performs a specific, named role.
180 The SV can be a Perl object or the name of a Perl class.
181
182 =cut
183 */
184
185 #include "XSUB.h"
186
187 bool
188 Perl_sv_does_sv(pTHX_ SV *sv, SV *namesv, U32 flags)
189 {
190     SV *classname;
191     bool does_it;
192     SV *methodname;
193     dSP;
194
195     PERL_ARGS_ASSERT_SV_DOES_SV;
196     PERL_UNUSED_ARG(flags);
197
198     ENTER;
199     SAVETMPS;
200
201     SvGETMAGIC(sv);
202
203     if (!SvOK(sv) || !(SvROK(sv) || (SvPOK(sv) && SvCUR(sv)))) {
204         LEAVE;
205         return FALSE;
206     }
207
208     if (SvROK(sv) && SvOBJECT(SvRV(sv))) {
209         classname = sv_ref(NULL,SvRV(sv),TRUE);
210     } else {
211         classname = sv;
212     }
213
214     if (sv_eq(classname, namesv)) {
215         LEAVE;
216         return TRUE;
217     }
218
219     PUSHMARK(SP);
220     EXTEND(SP, 2);
221     PUSHs(sv);
222     PUSHs(namesv);
223     PUTBACK;
224
225     methodname = newSVpvs_flags("isa", SVs_TEMP);
226     /* ugly hack: use the SvSCREAM flag so S_method_common
227      * can figure out we're calling DOES() and not isa(),
228      * and report eventual errors correctly. --rgs */
229     SvSCREAM_on(methodname);
230     call_sv(methodname, G_SCALAR | G_METHOD);
231     SPAGAIN;
232
233     does_it = SvTRUE( TOPs );
234     FREETMPS;
235     LEAVE;
236
237     return does_it;
238 }
239
240 /*
241 =for apidoc sv_does
242
243 Like L</sv_does_pv>, but doesn't take a C<flags> parameter.
244
245 =cut
246 */
247
248 bool
249 Perl_sv_does(pTHX_ SV *sv, const char *const name)
250 {
251     PERL_ARGS_ASSERT_SV_DOES;
252     return sv_does_sv(sv, newSVpvn_flags(name, strlen(name), SVs_TEMP), 0);
253 }
254
255 /*
256 =for apidoc sv_does_pv
257
258 Like L</sv_does_sv>, but takes a nul-terminated string instead of an SV.
259
260 =cut
261 */
262
263
264 bool
265 Perl_sv_does_pv(pTHX_ SV *sv, const char *const name, U32 flags)
266 {
267     PERL_ARGS_ASSERT_SV_DOES_PV;
268     return sv_does_sv(sv, newSVpvn_flags(name, strlen(name), SVs_TEMP | flags), flags);
269 }
270
271 /*
272 =for apidoc sv_does_pvn
273
274 Like L</sv_does_sv>, but takes a string/length pair instead of an SV.
275
276 =cut
277 */
278
279 bool
280 Perl_sv_does_pvn(pTHX_ SV *sv, const char *const name, const STRLEN len, U32 flags)
281 {
282     PERL_ARGS_ASSERT_SV_DOES_PVN;
283
284     return sv_does_sv(sv, newSVpvn_flags(name, len, flags | SVs_TEMP), flags);
285 }
286
287 /*
288 =for apidoc croak_xs_usage
289
290 A specialised variant of C<croak()> for emitting the usage message for xsubs
291
292     croak_xs_usage(cv, "eee_yow");
293
294 works out the package name and subroutine name from C<cv>, and then calls
295 C<croak()>.  Hence if C<cv> is C<&ouch::awk>, it would call C<croak> as:
296
297  Perl_croak(aTHX_ "Usage: %"SVf"::%"SVf"(%s)", "ouch" "awk",
298                                                      "eee_yow");
299
300 =cut
301 */
302
303 void
304 Perl_croak_xs_usage(const CV *const cv, const char *const params)
305 {
306     /* Avoid CvGV as it requires aTHX.  */
307     const GV *gv = CvNAMED(cv) ? NULL : cv->sv_any->xcv_gv_u.xcv_gv;
308
309     PERL_ARGS_ASSERT_CROAK_XS_USAGE;
310
311     if (gv) got_gv: {
312         const HV *const stash = GvSTASH(gv);
313
314         if (HvNAME_get(stash))
315             /* diag_listed_as: SKIPME */
316             Perl_croak_nocontext("Usage: %"HEKf"::%"HEKf"(%s)",
317                                 HEKfARG(HvNAME_HEK(stash)),
318                                 HEKfARG(GvNAME_HEK(gv)),
319                                 params);
320         else
321             /* diag_listed_as: SKIPME */
322             Perl_croak_nocontext("Usage: %"HEKf"(%s)",
323                                 HEKfARG(GvNAME_HEK(gv)), params);
324     } else {
325         dTHX;
326         if ((gv = CvGV(cv))) goto got_gv;
327
328         /* Pants. I don't think that it should be possible to get here. */
329         /* diag_listed_as: SKIPME */
330         Perl_croak(aTHX_ "Usage: CODE(0x%"UVxf")(%s)", PTR2UV(cv), params);
331     }
332 }
333
334 XS(XS_UNIVERSAL_isa); /* prototype to pass -Wmissing-prototypes */
335 XS(XS_UNIVERSAL_isa)
336 {
337     dXSARGS;
338
339     if (items != 2)
340         croak_xs_usage(cv, "reference, kind");
341     else {
342         SV * const sv = ST(0);
343
344         SvGETMAGIC(sv);
345
346         if (!SvOK(sv) || !(SvROK(sv) || (SvPOK(sv) && SvCUR(sv))))
347             XSRETURN_UNDEF;
348
349         ST(0) = boolSV(sv_derived_from_sv(sv, ST(1), 0));
350         XSRETURN(1);
351     }
352 }
353
354 XS(XS_UNIVERSAL_can); /* prototype to pass -Wmissing-prototypes */
355 XS(XS_UNIVERSAL_can)
356 {
357     dXSARGS;
358     SV   *sv;
359     SV   *rv;
360     HV   *pkg = NULL;
361     GV   *iogv;
362
363     if (items != 2)
364         croak_xs_usage(cv, "object-ref, method");
365
366     sv = ST(0);
367
368     SvGETMAGIC(sv);
369
370     /* Reject undef and empty string.  Note that the string form takes
371        precedence here over the numeric form, as (!1)->foo treats the
372        invocant as the empty string, though it is a dualvar. */
373     if (!SvOK(sv) || (SvPOK(sv) && !SvCUR(sv)))
374         XSRETURN_UNDEF;
375
376     rv = &PL_sv_undef;
377
378     if (SvROK(sv)) {
379         sv = MUTABLE_SV(SvRV(sv));
380         if (SvOBJECT(sv))
381             pkg = SvSTASH(sv);
382         else if (isGV_with_GP(sv) && GvIO(sv))
383             pkg = SvSTASH(GvIO(sv));
384     }
385     else if (isGV_with_GP(sv) && GvIO(sv))
386         pkg = SvSTASH(GvIO(sv));
387     else if ((iogv = gv_fetchsv_nomg(sv, 0, SVt_PVIO)) && GvIO(iogv))
388         pkg = SvSTASH(GvIO(iogv));
389     else {
390         pkg = gv_stashsv(sv, 0);
391         if (!pkg)
392             pkg = gv_stashpvs("UNIVERSAL", 0);
393     }
394
395     if (pkg) {
396         GV * const gv = gv_fetchmethod_sv_flags(pkg, ST(1), 0);
397         if (gv && isGV(gv))
398             rv = sv_2mortal(newRV(MUTABLE_SV(GvCV(gv))));
399     }
400
401     ST(0) = rv;
402     XSRETURN(1);
403 }
404
405 XS(XS_UNIVERSAL_DOES); /* prototype to pass -Wmissing-prototypes */
406 XS(XS_UNIVERSAL_DOES)
407 {
408     dXSARGS;
409     PERL_UNUSED_ARG(cv);
410
411     if (items != 2)
412         Perl_croak(aTHX_ "Usage: invocant->DOES(kind)");
413     else {
414         SV * const sv = ST(0);
415         if (sv_does_sv( sv, ST(1), 0 ))
416             XSRETURN_YES;
417
418         XSRETURN_NO;
419     }
420 }
421
422 XS(XS_utf8_is_utf8); /* prototype to pass -Wmissing-prototypes */
423 XS(XS_utf8_is_utf8)
424 {
425      dXSARGS;
426      if (items != 1)
427          croak_xs_usage(cv, "sv");
428      else {
429         SV * const sv = ST(0);
430         SvGETMAGIC(sv);
431             if (SvUTF8(sv))
432                 XSRETURN_YES;
433             else
434                 XSRETURN_NO;
435      }
436      XSRETURN_EMPTY;
437 }
438
439 XS(XS_utf8_valid); /* prototype to pass -Wmissing-prototypes */
440 XS(XS_utf8_valid)
441 {
442      dXSARGS;
443      if (items != 1)
444          croak_xs_usage(cv, "sv");
445     else {
446         SV * const sv = ST(0);
447         STRLEN len;
448         const char * const s = SvPV_const(sv,len);
449         if (!SvUTF8(sv) || is_utf8_string((const U8*)s,len))
450             XSRETURN_YES;
451         else
452             XSRETURN_NO;
453     }
454      XSRETURN_EMPTY;
455 }
456
457 XS(XS_utf8_encode); /* prototype to pass -Wmissing-prototypes */
458 XS(XS_utf8_encode)
459 {
460     dXSARGS;
461     if (items != 1)
462         croak_xs_usage(cv, "sv");
463     sv_utf8_encode(ST(0));
464     SvSETMAGIC(ST(0));
465     XSRETURN_EMPTY;
466 }
467
468 XS(XS_utf8_decode); /* prototype to pass -Wmissing-prototypes */
469 XS(XS_utf8_decode)
470 {
471     dXSARGS;
472     if (items != 1)
473         croak_xs_usage(cv, "sv");
474     else {
475         SV * const sv = ST(0);
476         bool RETVAL;
477         SvPV_force_nolen(sv);
478         RETVAL = sv_utf8_decode(sv);
479         SvSETMAGIC(sv);
480         ST(0) = boolSV(RETVAL);
481     }
482     XSRETURN(1);
483 }
484
485 XS(XS_utf8_upgrade); /* prototype to pass -Wmissing-prototypes */
486 XS(XS_utf8_upgrade)
487 {
488     dXSARGS;
489     if (items != 1)
490         croak_xs_usage(cv, "sv");
491     else {
492         SV * const sv = ST(0);
493         STRLEN  RETVAL;
494         dXSTARG;
495
496         RETVAL = sv_utf8_upgrade(sv);
497         XSprePUSH; PUSHi((IV)RETVAL);
498     }
499     XSRETURN(1);
500 }
501
502 XS(XS_utf8_downgrade); /* prototype to pass -Wmissing-prototypes */
503 XS(XS_utf8_downgrade)
504 {
505     dXSARGS;
506     if (items < 1 || items > 2)
507         croak_xs_usage(cv, "sv, failok=0");
508     else {
509         SV * const sv = ST(0);
510         const bool failok = (items < 2) ? 0 : SvTRUE(ST(1)) ? 1 : 0;
511         const bool RETVAL = sv_utf8_downgrade(sv, failok);
512
513         ST(0) = boolSV(RETVAL);
514     }
515     XSRETURN(1);
516 }
517
518 XS(XS_utf8_native_to_unicode); /* prototype to pass -Wmissing-prototypes */
519 XS(XS_utf8_native_to_unicode)
520 {
521  dXSARGS;
522  const UV uv = SvUV(ST(0));
523
524  if (items > 1)
525      croak_xs_usage(cv, "sv");
526
527  ST(0) = sv_2mortal(newSVuv(NATIVE_TO_UNI(uv)));
528  XSRETURN(1);
529 }
530
531 XS(XS_utf8_unicode_to_native); /* prototype to pass -Wmissing-prototypes */
532 XS(XS_utf8_unicode_to_native)
533 {
534  dXSARGS;
535  const UV uv = SvUV(ST(0));
536
537  if (items > 1)
538      croak_xs_usage(cv, "sv");
539
540  ST(0) = sv_2mortal(newSVuv(UNI_TO_NATIVE(uv)));
541  XSRETURN(1);
542 }
543
544 XS(XS_Internals_SvREADONLY); /* prototype to pass -Wmissing-prototypes */
545 XS(XS_Internals_SvREADONLY)     /* This is dangerous stuff. */
546 {
547     dXSARGS;
548     SV * const svz = ST(0);
549     SV * sv;
550     PERL_UNUSED_ARG(cv);
551
552     /* [perl #77776] - called as &foo() not foo() */
553     if (!SvROK(svz))
554         croak_xs_usage(cv, "SCALAR[, ON]");
555
556     sv = SvRV(svz);
557
558     if (items == 1) {
559          if (SvREADONLY(sv))
560              XSRETURN_YES;
561          else
562              XSRETURN_NO;
563     }
564     else if (items == 2) {
565         if (SvTRUE(ST(1))) {
566             SvFLAGS(sv) |= SVf_READONLY;
567             XSRETURN_YES;
568         }
569         else {
570             /* I hope you really know what you are doing. */
571             SvFLAGS(sv) &=~ SVf_READONLY;
572             XSRETURN_NO;
573         }
574     }
575     XSRETURN_UNDEF; /* Can't happen. */
576 }
577
578 XS(XS_constant__make_const); /* prototype to pass -Wmissing-prototypes */
579 XS(XS_constant__make_const)     /* This is dangerous stuff. */
580 {
581     dXSARGS;
582     SV * const svz = ST(0);
583     SV * sv;
584     PERL_UNUSED_ARG(cv);
585
586     /* [perl #77776] - called as &foo() not foo() */
587     if (!SvROK(svz) || items != 1)
588         croak_xs_usage(cv, "SCALAR");
589
590     sv = SvRV(svz);
591
592     SvREADONLY_on(sv);
593     if (SvTYPE(sv) == SVt_PVAV && AvFILLp(sv) != -1) {
594         /* for constant.pm; nobody else should be calling this
595            on arrays anyway. */
596         SV **svp;
597         for (svp = AvARRAY(sv) + AvFILLp(sv)
598            ; svp >= AvARRAY(sv)
599            ; --svp)
600             if (*svp) SvPADTMP_on(*svp);
601     }
602     XSRETURN(0);
603 }
604
605 XS(XS_Internals_SvREFCNT); /* prototype to pass -Wmissing-prototypes */
606 XS(XS_Internals_SvREFCNT)       /* This is dangerous stuff. */
607 {
608     dXSARGS;
609     SV * const svz = ST(0);
610     SV * sv;
611     U32 refcnt;
612     PERL_UNUSED_ARG(cv);
613
614     /* [perl #77776] - called as &foo() not foo() */
615     if ((items != 1 && items != 2) || !SvROK(svz))
616         croak_xs_usage(cv, "SCALAR[, REFCOUNT]");
617
618     sv = SvRV(svz);
619
620          /* I hope you really know what you are doing. */
621     /* idea is for SvREFCNT(sv) to be accessed only once */
622     refcnt = items == 2 ?
623                 /* we free one ref on exit */
624                 (SvREFCNT(sv) = SvUV(ST(1)) + 1)
625                 : SvREFCNT(sv);
626     XSRETURN_UV(refcnt - 1); /* Minus the ref created for us. */        
627
628 }
629
630 XS(XS_Internals_hv_clear_placehold); /* prototype to pass -Wmissing-prototypes */
631 XS(XS_Internals_hv_clear_placehold)
632 {
633     dXSARGS;
634
635     if (items != 1 || !SvROK(ST(0)))
636         croak_xs_usage(cv, "hv");
637     else {
638         HV * const hv = MUTABLE_HV(SvRV(ST(0)));
639         hv_clear_placeholders(hv);
640         XSRETURN(0);
641     }
642 }
643
644 XS(XS_PerlIO_get_layers); /* prototype to pass -Wmissing-prototypes */
645 XS(XS_PerlIO_get_layers)
646 {
647     dXSARGS;
648     if (items < 1 || items % 2 == 0)
649         croak_xs_usage(cv, "filehandle[,args]");
650 #if defined(USE_PERLIO)
651     {
652         SV *    sv;
653         GV *    gv;
654         IO *    io;
655         bool    input = TRUE;
656         bool    details = FALSE;
657
658         if (items > 1) {
659              SV * const *svp;
660              for (svp = MARK + 2; svp <= SP; svp += 2) {
661                   SV * const * const varp = svp;
662                   SV * const * const valp = svp + 1;
663                   STRLEN klen;
664                   const char * const key = SvPV_const(*varp, klen);
665
666                   switch (*key) {
667                   case 'i':
668                        if (klen == 5 && memEQ(key, "input", 5)) {
669                             input = SvTRUE(*valp);
670                             break;
671                        }
672                        goto fail;
673                   case 'o': 
674                        if (klen == 6 && memEQ(key, "output", 6)) {
675                             input = !SvTRUE(*valp);
676                             break;
677                        }
678                        goto fail;
679                   case 'd':
680                        if (klen == 7 && memEQ(key, "details", 7)) {
681                             details = SvTRUE(*valp);
682                             break;
683                        }
684                        goto fail;
685                   default:
686                   fail:
687                        Perl_croak(aTHX_
688                                   "get_layers: unknown argument '%s'",
689                                   key);
690                   }
691              }
692
693              SP -= (items - 1);
694         }
695
696         sv = POPs;
697         gv = MAYBE_DEREF_GV(sv);
698
699         if (!gv && !SvROK(sv))
700             gv = gv_fetchsv_nomg(sv, 0, SVt_PVIO);
701
702         if (gv && (io = GvIO(gv))) {
703              AV* const av = PerlIO_get_layers(aTHX_ input ?
704                                         IoIFP(io) : IoOFP(io));
705              SSize_t i;
706              const SSize_t last = av_tindex(av);
707              SSize_t nitem = 0;
708              
709              for (i = last; i >= 0; i -= 3) {
710                   SV * const * const namsvp = av_fetch(av, i - 2, FALSE);
711                   SV * const * const argsvp = av_fetch(av, i - 1, FALSE);
712                   SV * const * const flgsvp = av_fetch(av, i,     FALSE);
713
714                   const bool namok = namsvp && *namsvp && SvPOK(*namsvp);
715                   const bool argok = argsvp && *argsvp && SvPOK(*argsvp);
716                   const bool flgok = flgsvp && *flgsvp && SvIOK(*flgsvp);
717
718                   EXTEND(SP, 3); /* Three is the max in all branches: better check just once */
719                   if (details) {
720                       /* Indents of 5? Yuck.  */
721                       /* We know that PerlIO_get_layers creates a new SV for
722                          the name and flags, so we can just take a reference
723                          and "steal" it when we free the AV below.  */
724                        PUSHs(namok
725                               ? sv_2mortal(SvREFCNT_inc_simple_NN(*namsvp))
726                               : &PL_sv_undef);
727                        PUSHs(argok
728                               ? newSVpvn_flags(SvPVX_const(*argsvp),
729                                                SvCUR(*argsvp),
730                                                (SvUTF8(*argsvp) ? SVf_UTF8 : 0)
731                                                | SVs_TEMP)
732                               : &PL_sv_undef);
733                        PUSHs(flgok
734                               ? sv_2mortal(SvREFCNT_inc_simple_NN(*flgsvp))
735                               : &PL_sv_undef);
736                        nitem += 3;
737                   }
738                   else {
739                        if (namok && argok)
740                             PUSHs(sv_2mortal(Perl_newSVpvf(aTHX_ "%"SVf"(%"SVf")",
741                                                  SVfARG(*namsvp),
742                                                  SVfARG(*argsvp))));
743                        else if (namok)
744                             PUSHs(sv_2mortal(SvREFCNT_inc_simple_NN(*namsvp)));
745                        else
746                             PUSHs(&PL_sv_undef);
747                        nitem++;
748                        if (flgok) {
749                             const IV flags = SvIVX(*flgsvp);
750
751                             if (flags & PERLIO_F_UTF8) {
752                                  PUSHs(newSVpvs_flags("utf8", SVs_TEMP));
753                                  nitem++;
754                             }
755                        }
756                   }
757              }
758
759              SvREFCNT_dec(av);
760
761              XSRETURN(nitem);
762         }
763     }
764 #endif
765
766     XSRETURN(0);
767 }
768
769 XS(XS_re_is_regexp); /* prototype to pass -Wmissing-prototypes */
770 XS(XS_re_is_regexp)
771 {
772     dXSARGS;
773     PERL_UNUSED_VAR(cv);
774
775     if (items != 1)
776         croak_xs_usage(cv, "sv");
777
778     if (SvRXOK(ST(0))) {
779         XSRETURN_YES;
780     } else {
781         XSRETURN_NO;
782     }
783 }
784
785 XS(XS_re_regnames_count); /* prototype to pass -Wmissing-prototypes */
786 XS(XS_re_regnames_count)
787 {
788     REGEXP *rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
789     SV * ret;
790     dXSARGS;
791
792     if (items != 0)
793         croak_xs_usage(cv, "");
794
795     if (!rx)
796         XSRETURN_UNDEF;
797
798     ret = CALLREG_NAMED_BUFF_COUNT(rx);
799
800     SPAGAIN;
801     PUSHs(ret ? sv_2mortal(ret) : &PL_sv_undef);
802     XSRETURN(1);
803 }
804
805 XS(XS_re_regname); /* prototype to pass -Wmissing-prototypes */
806 XS(XS_re_regname)
807 {
808     dXSARGS;
809     REGEXP * rx;
810     U32 flags;
811     SV * ret;
812
813     if (items < 1 || items > 2)
814         croak_xs_usage(cv, "name[, all ]");
815
816     SP -= items;
817     PUTBACK;
818
819     rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
820
821     if (!rx)
822         XSRETURN_UNDEF;
823
824     if (items == 2 && SvTRUE(ST(1))) {
825         flags = RXapif_ALL;
826     } else {
827         flags = RXapif_ONE;
828     }
829     ret = CALLREG_NAMED_BUFF_FETCH(rx, ST(0), (flags | RXapif_REGNAME));
830
831     SPAGAIN;
832     PUSHs(ret ? sv_2mortal(ret) : &PL_sv_undef);
833     XSRETURN(1);
834 }
835
836
837 XS(XS_re_regnames); /* prototype to pass -Wmissing-prototypes */
838 XS(XS_re_regnames)
839 {
840     dXSARGS;
841     REGEXP * rx;
842     U32 flags;
843     SV *ret;
844     AV *av;
845     SSize_t length;
846     SSize_t i;
847     SV **entry;
848
849     if (items > 1)
850         croak_xs_usage(cv, "[all]");
851
852     rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
853
854     if (!rx)
855         XSRETURN_UNDEF;
856
857     if (items == 1 && SvTRUE(ST(0))) {
858         flags = RXapif_ALL;
859     } else {
860         flags = RXapif_ONE;
861     }
862
863     SP -= items;
864     PUTBACK;
865
866     ret = CALLREG_NAMED_BUFF_ALL(rx, (flags | RXapif_REGNAMES));
867
868     SPAGAIN;
869
870     if (!ret)
871         XSRETURN_UNDEF;
872
873     av = MUTABLE_AV(SvRV(ret));
874     length = av_tindex(av);
875
876     EXTEND(SP, length+1); /* better extend stack just once */
877     for (i = 0; i <= length; i++) {
878         entry = av_fetch(av, i, FALSE);
879         
880         if (!entry)
881             Perl_croak(aTHX_ "NULL array element in re::regnames()");
882
883         mPUSHs(SvREFCNT_inc_simple_NN(*entry));
884     }
885
886     SvREFCNT_dec(ret);
887
888     PUTBACK;
889     return;
890 }
891
892 XS(XS_re_regexp_pattern); /* prototype to pass -Wmissing-prototypes */
893 XS(XS_re_regexp_pattern)
894 {
895     dXSARGS;
896     REGEXP *re;
897     U8 const gimme = GIMME_V;
898
899     EXTEND(SP, 2);
900     SP -= items;
901     if (items != 1)
902         croak_xs_usage(cv, "sv");
903
904     /*
905        Checks if a reference is a regex or not. If the parameter is
906        not a ref, or is not the result of a qr// then returns false
907        in scalar context and an empty list in list context.
908        Otherwise in list context it returns the pattern and the
909        modifiers, in scalar context it returns the pattern just as it
910        would if the qr// was stringified normally, regardless as
911        to the class of the variable and any stringification overloads
912        on the object.
913     */
914
915     if ((re = SvRX(ST(0)))) /* assign deliberate */
916     {
917         /* Houston, we have a regex! */
918         SV *pattern;
919
920         if ( gimme == G_ARRAY ) {
921             STRLEN left = 0;
922             char reflags[sizeof(INT_PAT_MODS) + MAX_CHARSET_NAME_LENGTH];
923             const char *fptr;
924             char ch;
925             U16 match_flags;
926
927             /*
928                we are in list context so stringify
929                the modifiers that apply. We ignore "negative
930                modifiers" in this scenario, and the default character set
931             */
932
933             if (get_regex_charset(RX_EXTFLAGS(re)) != REGEX_DEPENDS_CHARSET) {
934                 STRLEN len;
935                 const char* const name = get_regex_charset_name(RX_EXTFLAGS(re),
936                                                                 &len);
937                 Copy(name, reflags + left, len, char);
938                 left += len;
939             }
940             fptr = INT_PAT_MODS;
941             match_flags = (U16)((RX_EXTFLAGS(re) & RXf_PMf_COMPILETIME)
942                                     >> RXf_PMf_STD_PMMOD_SHIFT);
943
944             while((ch = *fptr++)) {
945                 if(match_flags & 1) {
946                     reflags[left++] = ch;
947                 }
948                 match_flags >>= 1;
949             }
950
951             pattern = newSVpvn_flags(RX_PRECOMP(re),RX_PRELEN(re),
952                                      (RX_UTF8(re) ? SVf_UTF8 : 0) | SVs_TEMP);
953
954             /* return the pattern and the modifiers */
955             PUSHs(pattern);
956             PUSHs(newSVpvn_flags(reflags, left, SVs_TEMP));
957             XSRETURN(2);
958         } else {
959             /* Scalar, so use the string that Perl would return */
960             /* return the pattern in (?msixn:..) format */
961 #if PERL_VERSION >= 11
962             pattern = sv_2mortal(newSVsv(MUTABLE_SV(re)));
963 #else
964             pattern = newSVpvn_flags(RX_WRAPPED(re), RX_WRAPLEN(re),
965                                      (RX_UTF8(re) ? SVf_UTF8 : 0) | SVs_TEMP);
966 #endif
967             PUSHs(pattern);
968             XSRETURN(1);
969         }
970     } else {
971         /* It ain't a regexp folks */
972         if ( gimme == G_ARRAY ) {
973             /* return the empty list */
974             XSRETURN_EMPTY;
975         } else {
976             /* Because of the (?:..) wrapping involved in a
977                stringified pattern it is impossible to get a
978                result for a real regexp that would evaluate to
979                false. Therefore we can return PL_sv_no to signify
980                that the object is not a regex, this means that one
981                can say
982
983                  if (regex($might_be_a_regex) eq '(?:foo)') { }
984
985                and not worry about undefined values.
986             */
987             XSRETURN_NO;
988         }
989     }
990     NOT_REACHED; /* NOTREACHED */
991 }
992
993 #include "vutil.h"
994 #include "vxs.inc"
995
996 struct xsub_details {
997     const char *name;
998     XSUBADDR_t xsub;
999     const char *proto;
1000 };
1001
1002 static const struct xsub_details details[] = {
1003     {"UNIVERSAL::isa", XS_UNIVERSAL_isa, NULL},
1004     {"UNIVERSAL::can", XS_UNIVERSAL_can, NULL},
1005     {"UNIVERSAL::DOES", XS_UNIVERSAL_DOES, NULL},
1006 #define VXS_XSUB_DETAILS
1007 #include "vxs.inc"
1008 #undef VXS_XSUB_DETAILS
1009     {"utf8::is_utf8", XS_utf8_is_utf8, NULL},
1010     {"utf8::valid", XS_utf8_valid, NULL},
1011     {"utf8::encode", XS_utf8_encode, NULL},
1012     {"utf8::decode", XS_utf8_decode, NULL},
1013     {"utf8::upgrade", XS_utf8_upgrade, NULL},
1014     {"utf8::downgrade", XS_utf8_downgrade, NULL},
1015     {"utf8::native_to_unicode", XS_utf8_native_to_unicode, NULL},
1016     {"utf8::unicode_to_native", XS_utf8_unicode_to_native, NULL},
1017     {"Internals::SvREADONLY", XS_Internals_SvREADONLY, "\\[$%@];$"},
1018     {"Internals::SvREFCNT", XS_Internals_SvREFCNT, "\\[$%@];$"},
1019     {"Internals::hv_clear_placeholders", XS_Internals_hv_clear_placehold, "\\%"},
1020     {"constant::_make_const", XS_constant__make_const, "\\[$@]"},
1021     {"PerlIO::get_layers", XS_PerlIO_get_layers, "*;@"},
1022     {"re::is_regexp", XS_re_is_regexp, "$"},
1023     {"re::regname", XS_re_regname, ";$$"},
1024     {"re::regnames", XS_re_regnames, ";$"},
1025     {"re::regnames_count", XS_re_regnames_count, ""},
1026     {"re::regexp_pattern", XS_re_regexp_pattern, "$"},
1027 };
1028
1029 STATIC OP*
1030 optimize_out_native_convert_function(pTHX_ OP* entersubop,
1031                                            GV* namegv,
1032                                            SV* protosv)
1033 {
1034     /* Optimizes out an identity function, i.e., one that just returns its
1035      * argument.  The passed in function is assumed to be an identity function,
1036      * with no checking.  This is designed to be called for utf8_to_native()
1037      * and native_to_utf8() on ASCII platforms, as they just return their
1038      * arguments, but it could work on any such function.
1039      *
1040      * The code is mostly just cargo-culted from Memoize::Lift */
1041
1042     OP *pushop, *argop;
1043     OP *parent;
1044     SV* prototype = newSVpvs("$");
1045
1046     PERL_UNUSED_ARG(protosv);
1047
1048     assert(entersubop->op_type == OP_ENTERSUB);
1049
1050     entersubop = ck_entersub_args_proto(entersubop, namegv, prototype);
1051     parent = entersubop;
1052
1053     SvREFCNT_dec(prototype);
1054
1055     pushop = cUNOPx(entersubop)->op_first;
1056     if (! OpHAS_SIBLING(pushop)) {
1057         parent = pushop;
1058         pushop = cUNOPx(pushop)->op_first;
1059     }
1060     argop = OpSIBLING(pushop);
1061
1062     /* Carry on without doing the optimization if it is not something we're
1063      * expecting, so continues to work */
1064     if (   ! argop
1065         || ! OpHAS_SIBLING(argop)
1066         ||   OpHAS_SIBLING(OpSIBLING(argop))
1067     ) {
1068         return entersubop;
1069     }
1070
1071     /* cut argop from the subtree */
1072     (void)op_sibling_splice(parent, pushop, 1, NULL);
1073
1074     op_free(entersubop);
1075     return argop;
1076 }
1077
1078 void
1079 Perl_boot_core_UNIVERSAL(pTHX)
1080 {
1081     static const char file[] = __FILE__;
1082     const struct xsub_details *xsub = details;
1083     const struct xsub_details *end = C_ARRAY_END(details);
1084
1085     do {
1086         newXS_flags(xsub->name, xsub->xsub, file, xsub->proto, 0);
1087     } while (++xsub < end);
1088
1089 #ifndef EBCDIC
1090     { /* On ASCII platforms these functions just return their argument, so can
1091          be optimized away */
1092
1093         CV* to_native_cv = get_cv("utf8::unicode_to_native", 0);
1094         CV* to_unicode_cv = get_cv("utf8::native_to_unicode", 0);
1095
1096         cv_set_call_checker(to_native_cv,
1097                             optimize_out_native_convert_function,
1098                             (SV*) to_native_cv);
1099         cv_set_call_checker(to_unicode_cv,
1100                             optimize_out_native_convert_function,
1101                             (SV*) to_unicode_cv);
1102     }
1103 #endif
1104
1105     /* Providing a Regexp::DESTROY fixes #21347. See test in t/op/ref.t  */
1106     {
1107         CV * const cv =
1108             newCONSTSUB(get_hv("Regexp::", GV_ADD), "DESTROY", NULL);
1109         char ** cvfile = &CvFILE(cv);
1110         char * oldfile = *cvfile;
1111         CvDYNFILE_off(cv);
1112         *cvfile = (char *)file;
1113         Safefree(oldfile);
1114     }
1115 }
1116
1117 /*
1118  * ex: set ts=8 sts=4 sw=4 et:
1119  */