(perl #126162) improve stat @array handling
[perl.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
770 XS(XS_re_is_regexp); /* prototype to pass -Wmissing-prototypes */
771 XS(XS_re_is_regexp)
772 {
773     dXSARGS;
774     PERL_UNUSED_VAR(cv);
775
776     if (items != 1)
777         croak_xs_usage(cv, "sv");
778
779     if (SvRXOK(ST(0))) {
780         XSRETURN_YES;
781     } else {
782         XSRETURN_NO;
783     }
784 }
785
786 XS(XS_re_regnames_count); /* prototype to pass -Wmissing-prototypes */
787 XS(XS_re_regnames_count)
788 {
789     REGEXP *rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
790     SV * ret;
791     dXSARGS;
792
793     if (items != 0)
794         croak_xs_usage(cv, "");
795
796     SP -= items;
797     PUTBACK;
798
799     if (!rx)
800         XSRETURN_UNDEF;
801
802     ret = CALLREG_NAMED_BUFF_COUNT(rx);
803
804     SPAGAIN;
805     PUSHs(ret ? sv_2mortal(ret) : &PL_sv_undef);
806     XSRETURN(1);
807 }
808
809 XS(XS_re_regname); /* prototype to pass -Wmissing-prototypes */
810 XS(XS_re_regname)
811 {
812     dXSARGS;
813     REGEXP * rx;
814     U32 flags;
815     SV * ret;
816
817     if (items < 1 || items > 2)
818         croak_xs_usage(cv, "name[, all ]");
819
820     SP -= items;
821     PUTBACK;
822
823     rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
824
825     if (!rx)
826         XSRETURN_UNDEF;
827
828     if (items == 2 && SvTRUE(ST(1))) {
829         flags = RXapif_ALL;
830     } else {
831         flags = RXapif_ONE;
832     }
833     ret = CALLREG_NAMED_BUFF_FETCH(rx, ST(0), (flags | RXapif_REGNAME));
834
835     SPAGAIN;
836     PUSHs(ret ? sv_2mortal(ret) : &PL_sv_undef);
837     XSRETURN(1);
838 }
839
840
841 XS(XS_re_regnames); /* prototype to pass -Wmissing-prototypes */
842 XS(XS_re_regnames)
843 {
844     dXSARGS;
845     REGEXP * rx;
846     U32 flags;
847     SV *ret;
848     AV *av;
849     SSize_t length;
850     SSize_t i;
851     SV **entry;
852
853     if (items > 1)
854         croak_xs_usage(cv, "[all]");
855
856     rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
857
858     if (!rx)
859         XSRETURN_UNDEF;
860
861     if (items == 1 && SvTRUE(ST(0))) {
862         flags = RXapif_ALL;
863     } else {
864         flags = RXapif_ONE;
865     }
866
867     SP -= items;
868     PUTBACK;
869
870     ret = CALLREG_NAMED_BUFF_ALL(rx, (flags | RXapif_REGNAMES));
871
872     SPAGAIN;
873
874     if (!ret)
875         XSRETURN_UNDEF;
876
877     av = MUTABLE_AV(SvRV(ret));
878     length = av_tindex(av);
879
880     EXTEND(SP, length+1); /* better extend stack just once */
881     for (i = 0; i <= length; i++) {
882         entry = av_fetch(av, i, FALSE);
883         
884         if (!entry)
885             Perl_croak(aTHX_ "NULL array element in re::regnames()");
886
887         mPUSHs(SvREFCNT_inc_simple_NN(*entry));
888     }
889
890     SvREFCNT_dec(ret);
891
892     PUTBACK;
893     return;
894 }
895
896 XS(XS_re_regexp_pattern); /* prototype to pass -Wmissing-prototypes */
897 XS(XS_re_regexp_pattern)
898 {
899     dXSARGS;
900     REGEXP *re;
901     U8 const gimme = GIMME_V;
902
903     EXTEND(SP, 2);
904     SP -= items;
905     if (items != 1)
906         croak_xs_usage(cv, "sv");
907
908     /*
909        Checks if a reference is a regex or not. If the parameter is
910        not a ref, or is not the result of a qr// then returns false
911        in scalar context and an empty list in list context.
912        Otherwise in list context it returns the pattern and the
913        modifiers, in scalar context it returns the pattern just as it
914        would if the qr// was stringified normally, regardless as
915        to the class of the variable and any stringification overloads
916        on the object.
917     */
918
919     if ((re = SvRX(ST(0)))) /* assign deliberate */
920     {
921         /* Houston, we have a regex! */
922         SV *pattern;
923
924         if ( gimme == G_ARRAY ) {
925             STRLEN left = 0;
926             char reflags[sizeof(INT_PAT_MODS) + MAX_CHARSET_NAME_LENGTH];
927             const char *fptr;
928             char ch;
929             U16 match_flags;
930
931             /*
932                we are in list context so stringify
933                the modifiers that apply. We ignore "negative
934                modifiers" in this scenario, and the default character set
935             */
936
937             if (get_regex_charset(RX_EXTFLAGS(re)) != REGEX_DEPENDS_CHARSET) {
938                 STRLEN len;
939                 const char* const name = get_regex_charset_name(RX_EXTFLAGS(re),
940                                                                 &len);
941                 Copy(name, reflags + left, len, char);
942                 left += len;
943             }
944             fptr = INT_PAT_MODS;
945             match_flags = (U16)((RX_EXTFLAGS(re) & RXf_PMf_COMPILETIME)
946                                     >> RXf_PMf_STD_PMMOD_SHIFT);
947
948             while((ch = *fptr++)) {
949                 if(match_flags & 1) {
950                     reflags[left++] = ch;
951                 }
952                 match_flags >>= 1;
953             }
954
955             pattern = newSVpvn_flags(RX_PRECOMP(re),RX_PRELEN(re),
956                                      (RX_UTF8(re) ? SVf_UTF8 : 0) | SVs_TEMP);
957
958             /* return the pattern and the modifiers */
959             PUSHs(pattern);
960             PUSHs(newSVpvn_flags(reflags, left, SVs_TEMP));
961             XSRETURN(2);
962         } else {
963             /* Scalar, so use the string that Perl would return */
964             /* return the pattern in (?msixn:..) format */
965 #if PERL_VERSION >= 11
966             pattern = sv_2mortal(newSVsv(MUTABLE_SV(re)));
967 #else
968             pattern = newSVpvn_flags(RX_WRAPPED(re), RX_WRAPLEN(re),
969                                      (RX_UTF8(re) ? SVf_UTF8 : 0) | SVs_TEMP);
970 #endif
971             PUSHs(pattern);
972             XSRETURN(1);
973         }
974     } else {
975         /* It ain't a regexp folks */
976         if ( gimme == G_ARRAY ) {
977             /* return the empty list */
978             XSRETURN_EMPTY;
979         } else {
980             /* Because of the (?:..) wrapping involved in a
981                stringified pattern it is impossible to get a
982                result for a real regexp that would evaluate to
983                false. Therefore we can return PL_sv_no to signify
984                that the object is not a regex, this means that one
985                can say
986
987                  if (regex($might_be_a_regex) eq '(?:foo)') { }
988
989                and not worry about undefined values.
990             */
991             XSRETURN_NO;
992         }
993     }
994     NOT_REACHED; /* NOTREACHED */
995 }
996
997 #include "vutil.h"
998 #include "vxs.inc"
999
1000 struct xsub_details {
1001     const char *name;
1002     XSUBADDR_t xsub;
1003     const char *proto;
1004 };
1005
1006 static const struct xsub_details details[] = {
1007     {"UNIVERSAL::isa", XS_UNIVERSAL_isa, NULL},
1008     {"UNIVERSAL::can", XS_UNIVERSAL_can, NULL},
1009     {"UNIVERSAL::DOES", XS_UNIVERSAL_DOES, NULL},
1010 #define VXS_XSUB_DETAILS
1011 #include "vxs.inc"
1012 #undef VXS_XSUB_DETAILS
1013     {"utf8::is_utf8", XS_utf8_is_utf8, NULL},
1014     {"utf8::valid", XS_utf8_valid, NULL},
1015     {"utf8::encode", XS_utf8_encode, NULL},
1016     {"utf8::decode", XS_utf8_decode, NULL},
1017     {"utf8::upgrade", XS_utf8_upgrade, NULL},
1018     {"utf8::downgrade", XS_utf8_downgrade, NULL},
1019     {"utf8::native_to_unicode", XS_utf8_native_to_unicode, NULL},
1020     {"utf8::unicode_to_native", XS_utf8_unicode_to_native, NULL},
1021     {"Internals::SvREADONLY", XS_Internals_SvREADONLY, "\\[$%@];$"},
1022     {"constant::_make_const", XS_constant__make_const, "\\[$@]"},
1023     {"Internals::SvREFCNT", XS_Internals_SvREFCNT, "\\[$%@];$"},
1024     {"Internals::hv_clear_placeholders", XS_Internals_hv_clear_placehold, "\\%"},
1025     {"PerlIO::get_layers", XS_PerlIO_get_layers, "*;@"},
1026     {"re::is_regexp", XS_re_is_regexp, "$"},
1027     {"re::regname", XS_re_regname, ";$$"},
1028     {"re::regnames", XS_re_regnames, ";$"},
1029     {"re::regnames_count", XS_re_regnames_count, ""},
1030     {"re::regexp_pattern", XS_re_regexp_pattern, "$"},
1031 };
1032
1033 STATIC OP*
1034 optimize_out_native_convert_function(pTHX_ OP* entersubop,
1035                                            GV* namegv,
1036                                            SV* protosv)
1037 {
1038     /* Optimizes out an identity function, i.e., one that just returns its
1039      * argument.  The passed in function is assumed to be an identity function,
1040      * with no checking.  This is designed to be called for utf8_to_native()
1041      * and native_to_utf8() on ASCII platforms, as they just return their
1042      * arguments, but it could work on any such function.
1043      *
1044      * The code is mostly just cargo-culted from Memoize::Lift */
1045
1046     OP *pushop, *argop;
1047     OP *parent;
1048     SV* prototype = newSVpvs("$");
1049
1050     PERL_UNUSED_ARG(protosv);
1051
1052     assert(entersubop->op_type == OP_ENTERSUB);
1053
1054     entersubop = ck_entersub_args_proto(entersubop, namegv, prototype);
1055     parent = entersubop;
1056
1057     SvREFCNT_dec(prototype);
1058
1059     pushop = cUNOPx(entersubop)->op_first;
1060     if (! OpHAS_SIBLING(pushop)) {
1061         parent = pushop;
1062         pushop = cUNOPx(pushop)->op_first;
1063     }
1064     argop = OpSIBLING(pushop);
1065
1066     /* Carry on without doing the optimization if it is not something we're
1067      * expecting, so continues to work */
1068     if (   ! argop
1069         || ! OpHAS_SIBLING(argop)
1070         ||   OpHAS_SIBLING(OpSIBLING(argop))
1071     ) {
1072         return entersubop;
1073     }
1074
1075     /* cut argop from the subtree */
1076     (void)op_sibling_splice(parent, pushop, 1, NULL);
1077
1078     op_free(entersubop);
1079     return argop;
1080 }
1081
1082 void
1083 Perl_boot_core_UNIVERSAL(pTHX)
1084 {
1085     static const char file[] = __FILE__;
1086     const struct xsub_details *xsub = details;
1087     const struct xsub_details *end = C_ARRAY_END(details);
1088
1089     do {
1090         newXS_flags(xsub->name, xsub->xsub, file, xsub->proto, 0);
1091     } while (++xsub < end);
1092
1093 #ifndef EBCDIC
1094     { /* On ASCII platforms these functions just return their argument, so can
1095          be optimized away */
1096
1097         CV* to_native_cv = get_cv("utf8::unicode_to_native", 0);
1098         CV* to_unicode_cv = get_cv("utf8::native_to_unicode", 0);
1099
1100         cv_set_call_checker(to_native_cv,
1101                             optimize_out_native_convert_function,
1102                             (SV*) to_native_cv);
1103         cv_set_call_checker(to_unicode_cv,
1104                             optimize_out_native_convert_function,
1105                             (SV*) to_unicode_cv);
1106     }
1107 #endif
1108
1109     /* Providing a Regexp::DESTROY fixes #21347. See test in t/op/ref.t  */
1110     {
1111         CV * const cv =
1112             newCONSTSUB(get_hv("Regexp::", GV_ADD), "DESTROY", NULL);
1113         char ** cvfile = &CvFILE(cv);
1114         char * oldfile = *cvfile;
1115         CvDYNFILE_off(cv);
1116         *cvfile = (char *)file;
1117         Safefree(oldfile);
1118     }
1119 }
1120
1121 /*
1122  * ex: set ts=8 sts=4 sw=4 et:
1123  */