This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
7cbaaf7e4859a30b179a7a4c0ebc7d7dcb9c34c5
[perl5.git] / universal.c
1 /*    universal.c
2  *
3  *    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
4  *    2005, 2006, 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 story
15  */
16
17 /* This file contains the code that implements the functions in Perl's
18  * UNIVERSAL package, such as UNIVERSAL->can().
19  */
20
21 #include "EXTERN.h"
22 #define PERL_IN_UNIVERSAL_C
23 #include "perl.h"
24
25 #ifdef USE_PERLIO
26 #include "perliol.h" /* For the PERLIO_F_XXX */
27 #endif
28
29 /*
30  * Contributed by Graham Barr  <Graham.Barr@tiuk.ti.com>
31  * The main guts of traverse_isa was actually copied from gv_fetchmeth
32  */
33
34 STATIC bool
35 S_isa_lookup(pTHX_ HV *stash, const char *name, HV* name_stash,
36              int len, int level)
37 {
38     dVAR;
39     AV* av;
40     GV* gv;
41     GV** gvp;
42     HV* hv = NULL;
43     SV* subgen = NULL;
44     const char *hvname;
45
46     /* A stash/class can go by many names (ie. User == main::User), so 
47        we compare the stash itself just in case */
48     if (name_stash && (stash == name_stash))
49         return TRUE;
50
51     hvname = HvNAME_get(stash);
52
53     if (strEQ(hvname, name))
54         return TRUE;
55
56     if (strEQ(name, "UNIVERSAL"))
57         return TRUE;
58
59     if (level > 100)
60         Perl_croak(aTHX_ "Recursive inheritance detected in package '%s'",
61                    hvname);
62
63     gvp = (GV**)hv_fetchs(stash, "::ISA::CACHE::", FALSE);
64
65     if (gvp && (gv = *gvp) != (GV*)&PL_sv_undef && (subgen = GvSV(gv))
66         && (hv = GvHV(gv)))
67     {
68         if (SvIV(subgen) == (IV)PL_sub_generation) {
69             SV* sv;
70             SV** const svp = (SV**)hv_fetch(hv, name, len, FALSE);
71             if (svp && (sv = *svp) != (SV*)&PL_sv_undef) {
72                 DEBUG_o( Perl_deb(aTHX_ "Using cached ISA %s for package %s\n",
73                                   name, hvname) );
74                 return (sv == &PL_sv_yes);
75             }
76         }
77         else {
78             DEBUG_o( Perl_deb(aTHX_ "ISA Cache in package %s is stale\n",
79                               hvname) );
80             hv_clear(hv);
81             sv_setiv(subgen, PL_sub_generation);
82         }
83     }
84
85     gvp = (GV**)hv_fetchs(stash, "ISA", FALSE);
86
87     if (gvp && (gv = *gvp) != (GV*)&PL_sv_undef && (av = GvAV(gv))) {
88         if (!hv || !subgen) {
89             gvp = (GV**)hv_fetchs(stash, "::ISA::CACHE::", TRUE);
90
91             gv = *gvp;
92
93             if (SvTYPE(gv) != SVt_PVGV)
94                 gv_init(gv, stash, "::ISA::CACHE::", 14, TRUE);
95
96             if (!hv)
97                 hv = GvHVn(gv);
98             if (!subgen) {
99                 subgen = newSViv(PL_sub_generation);
100                 GvSV(gv) = subgen;
101             }
102         }
103         if (hv) {
104             SV** svp = AvARRAY(av);
105             /* NOTE: No support for tied ISA */
106             I32 items = AvFILLp(av) + 1;
107             while (items--) {
108                 SV* const sv = *svp++;
109                 HV* const basestash = gv_stashsv(sv, FALSE);
110                 if (!basestash) {
111                     if (ckWARN(WARN_MISC))
112                         Perl_warner(aTHX_ packWARN(WARN_SYNTAX),
113                                     "Can't locate package %"SVf" for @%s::ISA",
114                                     (void*)sv, hvname);
115                     continue;
116                 }
117                 if (isa_lookup(basestash, name, name_stash, len, level + 1)) {
118                     (void)hv_store(hv,name,len,&PL_sv_yes,0);
119                     return TRUE;
120                 }
121             }
122             (void)hv_store(hv,name,len,&PL_sv_no,0);
123         }
124     }
125     return FALSE;
126 }
127
128 /*
129 =head1 SV Manipulation Functions
130
131 =for apidoc sv_derived_from
132
133 Returns a boolean indicating whether the SV is derived from the specified class
134 I<at the C level>.  To check derivation at the Perl level, call C<isa()> as a
135 normal Perl method.
136
137 =cut
138 */
139
140 bool
141 Perl_sv_derived_from(pTHX_ SV *sv, const char *name)
142 {
143     dVAR;
144     HV *stash;
145
146     SvGETMAGIC(sv);
147
148     if (SvROK(sv)) {
149         const char *type;
150         sv = SvRV(sv);
151         type = sv_reftype(sv,0);
152         if (type && strEQ(type,name))
153             return TRUE;
154         stash = SvOBJECT(sv) ? SvSTASH(sv) : NULL;
155     }
156     else {
157         stash = gv_stashsv(sv, FALSE);
158     }
159
160     if (stash) {
161         HV * const name_stash = gv_stashpv(name, FALSE);
162         return isa_lookup(stash, name, name_stash, strlen(name), 0);
163     }
164     else
165         return FALSE;
166
167 }
168
169 /*
170 =for apidoc sv_does
171
172 Returns a boolean indicating whether the SV performs a specific, named role.
173 The SV can be a Perl object or the name of a Perl class.
174
175 =cut
176 */
177
178 #include "XSUB.h"
179
180 bool
181 Perl_sv_does(pTHX_ SV *sv, const char *name)
182 {
183     const char *classname;
184     bool does_it;
185
186     dSP;
187     ENTER;
188     SAVETMPS;
189
190     SvGETMAGIC(sv);
191
192     if (!SvOK(sv) || !(SvROK(sv) || (SvPOK(sv) && SvCUR(sv))
193                 || (SvGMAGICAL(sv) && SvPOKp(sv) && SvCUR(sv))))
194         return FALSE;
195
196     if (sv_isobject(sv)) {
197         classname = sv_reftype(SvRV(sv),TRUE);
198     } else {
199         classname = SvPV(sv,PL_na);
200     }
201
202     if (strEQ(name,classname))
203         return TRUE;
204
205     PUSHMARK(SP);
206     XPUSHs(sv);
207     XPUSHs(sv_2mortal(newSVpv(name, 0)));
208     PUTBACK;
209
210     call_method("isa", G_SCALAR);
211     SPAGAIN;
212
213     does_it = SvTRUE( TOPs );
214     FREETMPS;
215     LEAVE;
216
217     return does_it;
218 }
219
220 PERL_XS_EXPORT_C void XS_UNIVERSAL_isa(pTHX_ CV *cv);
221 PERL_XS_EXPORT_C void XS_UNIVERSAL_can(pTHX_ CV *cv);
222 PERL_XS_EXPORT_C void XS_UNIVERSAL_DOES(pTHX_ CV *cv);
223 PERL_XS_EXPORT_C void XS_UNIVERSAL_VERSION(pTHX_ CV *cv);
224 XS(XS_version_new);
225 XS(XS_version_stringify);
226 XS(XS_version_numify);
227 XS(XS_version_normal);
228 XS(XS_version_vcmp);
229 XS(XS_version_boolean);
230 #ifdef HASATTRIBUTE_NORETURN
231 XS(XS_version_noop) __attribute__noreturn__;
232 #else
233 XS(XS_version_noop);
234 #endif
235 XS(XS_version_is_alpha);
236 XS(XS_version_qv);
237 XS(XS_utf8_is_utf8);
238 XS(XS_utf8_valid);
239 XS(XS_utf8_encode);
240 XS(XS_utf8_decode);
241 XS(XS_utf8_upgrade);
242 XS(XS_utf8_downgrade);
243 XS(XS_utf8_unicode_to_native);
244 XS(XS_utf8_native_to_unicode);
245 XS(XS_Internals_SvREADONLY);
246 XS(XS_Internals_SvREFCNT);
247 XS(XS_Internals_hv_clear_placehold);
248 XS(XS_PerlIO_get_layers);
249 XS(XS_Regexp_DESTROY);
250 XS(XS_Internals_hash_seed);
251 XS(XS_Internals_rehash_seed);
252 XS(XS_Internals_HvREHASH);
253 XS(XS_Internals_inc_sub_generation);
254
255 void
256 Perl_boot_core_UNIVERSAL(pTHX)
257 {
258     dVAR;
259     static const char file[] = __FILE__;
260
261     newXS("UNIVERSAL::isa",             XS_UNIVERSAL_isa,         file);
262     newXS("UNIVERSAL::can",             XS_UNIVERSAL_can,         file);
263     newXS("UNIVERSAL::DOES",            XS_UNIVERSAL_DOES,        file);
264     newXS("UNIVERSAL::VERSION",         XS_UNIVERSAL_VERSION,     file);
265     {
266         /* register the overloading (type 'A') magic */
267         PL_amagic_generation++;
268         /* Make it findable via fetchmethod */
269         newXS("version::()", XS_version_noop, file);
270         newXS("version::new", XS_version_new, file);
271         newXS("version::(\"\"", XS_version_stringify, file);
272         newXS("version::stringify", XS_version_stringify, file);
273         newXS("version::(0+", XS_version_numify, file);
274         newXS("version::numify", XS_version_numify, file);
275         newXS("version::normal", XS_version_normal, file);
276         newXS("version::(cmp", XS_version_vcmp, file);
277         newXS("version::(<=>", XS_version_vcmp, file);
278         newXS("version::vcmp", XS_version_vcmp, file);
279         newXS("version::(bool", XS_version_boolean, file);
280         newXS("version::boolean", XS_version_boolean, file);
281         newXS("version::(nomethod", XS_version_noop, file);
282         newXS("version::noop", XS_version_noop, file);
283         newXS("version::is_alpha", XS_version_is_alpha, file);
284         newXS("version::qv", XS_version_qv, file);
285     }
286     newXS("utf8::is_utf8", XS_utf8_is_utf8, file);
287     newXS("utf8::valid", XS_utf8_valid, file);
288     newXS("utf8::encode", XS_utf8_encode, file);
289     newXS("utf8::decode", XS_utf8_decode, file);
290     newXS("utf8::upgrade", XS_utf8_upgrade, file);
291     newXS("utf8::downgrade", XS_utf8_downgrade, file);
292     newXS("utf8::native_to_unicode", XS_utf8_native_to_unicode, file);
293     newXS("utf8::unicode_to_native", XS_utf8_unicode_to_native, file);
294     newXSproto("Internals::SvREADONLY",XS_Internals_SvREADONLY, file, "\\[$%@];$");
295     newXSproto("Internals::SvREFCNT",XS_Internals_SvREFCNT, file, "\\[$%@];$");
296     newXSproto("Internals::hv_clear_placeholders",
297                XS_Internals_hv_clear_placehold, file, "\\%");
298     newXSproto("PerlIO::get_layers",
299                XS_PerlIO_get_layers, file, "*;@");
300     newXS("Regexp::DESTROY", XS_Regexp_DESTROY, file);
301     newXSproto("Internals::hash_seed",XS_Internals_hash_seed, file, "");
302     newXSproto("Internals::rehash_seed",XS_Internals_rehash_seed, file, "");
303     newXSproto("Internals::HvREHASH", XS_Internals_HvREHASH, file, "\\%");
304     newXSproto("Internals::inc_sub_generation",XS_Internals_inc_sub_generation,
305                file, "");
306 }
307
308
309 XS(XS_UNIVERSAL_isa)
310 {
311     dVAR;
312     dXSARGS;
313
314     if (items != 2)
315         Perl_croak(aTHX_ "Usage: UNIVERSAL::isa(reference, kind)");
316     else {
317         SV * const sv = ST(0);
318         const char *name;
319
320         SvGETMAGIC(sv);
321
322         if (!SvOK(sv) || !(SvROK(sv) || (SvPOK(sv) && SvCUR(sv))
323                     || (SvGMAGICAL(sv) && SvPOKp(sv) && SvCUR(sv))))
324             XSRETURN_UNDEF;
325
326         name = SvPV_nolen_const(ST(1));
327
328         ST(0) = boolSV(sv_derived_from(sv, name));
329         XSRETURN(1);
330     }
331 }
332
333 XS(XS_UNIVERSAL_can)
334 {
335     dVAR;
336     dXSARGS;
337     SV   *sv;
338     const char *name;
339     SV   *rv;
340     HV   *pkg = NULL;
341
342     if (items != 2)
343         Perl_croak(aTHX_ "Usage: UNIVERSAL::can(object-ref, method)");
344
345     sv = ST(0);
346
347     SvGETMAGIC(sv);
348
349     if (!SvOK(sv) || !(SvROK(sv) || (SvPOK(sv) && SvCUR(sv))
350                 || (SvGMAGICAL(sv) && SvPOKp(sv) && SvCUR(sv))))
351         XSRETURN_UNDEF;
352
353     name = SvPV_nolen_const(ST(1));
354     rv = &PL_sv_undef;
355
356     if (SvROK(sv)) {
357         sv = (SV*)SvRV(sv);
358         if (SvOBJECT(sv))
359             pkg = SvSTASH(sv);
360     }
361     else {
362         pkg = gv_stashsv(sv, FALSE);
363     }
364
365     if (pkg) {
366         GV * const gv = gv_fetchmethod_autoload(pkg, name, FALSE);
367         if (gv && isGV(gv))
368             rv = sv_2mortal(newRV((SV*)GvCV(gv)));
369     }
370
371     ST(0) = rv;
372     XSRETURN(1);
373 }
374
375 XS(XS_UNIVERSAL_DOES)
376 {
377     dVAR;
378     dXSARGS;
379
380     if (items != 2)
381         Perl_croak(aTHX_ "Usage: invocant->does(kind)");
382     else {
383         SV * const sv = ST(0);
384         const char *name;
385
386         name = SvPV_nolen_const(ST(1));
387         if (sv_does( sv, name ))
388             XSRETURN_YES;
389
390         XSRETURN_NO;
391     }
392 }
393
394 XS(XS_UNIVERSAL_VERSION)
395 {
396     dVAR;
397     dXSARGS;
398     HV *pkg;
399     GV **gvp;
400     GV *gv;
401     SV *sv;
402     const char *undef;
403
404     if (SvROK(ST(0))) {
405         sv = (SV*)SvRV(ST(0));
406         if (!SvOBJECT(sv))
407             Perl_croak(aTHX_ "Cannot find version of an unblessed reference");
408         pkg = SvSTASH(sv);
409     }
410     else {
411         pkg = gv_stashsv(ST(0), FALSE);
412     }
413
414     gvp = pkg ? (GV**)hv_fetchs(pkg, "VERSION", FALSE) : NULL;
415
416     if (gvp && isGV(gv = *gvp) && (sv = GvSV(gv)) && SvOK(sv)) {
417         SV * const nsv = sv_newmortal();
418         sv_setsv(nsv, sv);
419         sv = nsv;
420         if ( !sv_derived_from(sv, "version"))
421             upg_version(sv);
422         undef = NULL;
423     }
424     else {
425         sv = (SV*)&PL_sv_undef;
426         undef = "(undef)";
427     }
428
429     if (items > 1) {
430         SV *req = ST(1);
431
432         if (undef) {
433             if (pkg) {
434                 const char * const name = HvNAME_get(pkg);
435                 Perl_croak(aTHX_
436                            "%s does not define $%s::VERSION--version check failed",
437                            name, name);
438             } else {
439                 Perl_croak(aTHX_
440                              "%s defines neither package nor VERSION--version check failed",
441                              SvPVx_nolen_const(ST(0)) );
442              }
443         }
444
445         if ( !sv_derived_from(req, "version")) {
446             /* req may very well be R/O, so create a new object */
447             SV * const nsv = sv_newmortal();
448             sv_setsv(nsv, req);
449             req = nsv;
450             upg_version(req);
451         }
452
453         if ( vcmp( req, sv ) > 0 )
454             Perl_croak(aTHX_ "%s version %"SVf" (%"SVf") required--"
455                        "this is only version %"SVf" (%"SVf")", HvNAME_get(pkg),
456                        (void*)vnumify(req),
457                        (void*)vnormal(req),
458                        (void*)vnumify(sv),
459                        (void*)vnormal(sv));
460     }
461
462     if ( SvOK(sv) && sv_derived_from(sv, "version") ) {
463         ST(0) = vnumify(sv);
464     } else {
465         ST(0) = sv;
466     }
467
468     XSRETURN(1);
469 }
470
471 XS(XS_version_new)
472 {
473     dVAR;
474     dXSARGS;
475     if (items > 3)
476         Perl_croak(aTHX_ "Usage: version::new(class, version)");
477     SP -= items;
478     {
479         SV *vs = ST(1);
480         SV *rv;
481         const char * const classname =
482             sv_isobject(ST(0)) /* get the class if called as an object method */
483                 ? HvNAME(SvSTASH(SvRV(ST(0))))
484                 : (char *)SvPV_nolen(ST(0));
485
486         if ( items == 1 || vs == &PL_sv_undef ) { /* no param or explicit undef */
487             /* create empty object */
488             vs = sv_newmortal();
489             sv_setpvn(vs,"",0);
490         }
491         else if ( items == 3 ) {
492             vs = sv_newmortal();
493             Perl_sv_setpvf(aTHX_ vs,"v%s",SvPV_nolen_const(ST(2)));
494         }
495
496         rv = new_version(vs);
497         if ( strcmp(classname,"version") != 0 ) /* inherited new() */
498             sv_bless(rv, gv_stashpv(classname,TRUE));
499
500         PUSHs(sv_2mortal(rv));
501         PUTBACK;
502         return;
503     }
504 }
505
506 XS(XS_version_stringify)
507 {
508      dVAR;
509      dXSARGS;
510      if (items < 1)
511           Perl_croak(aTHX_ "Usage: version::stringify(lobj, ...)");
512      SP -= items;
513      {
514           SV *  lobj;
515
516           if (sv_derived_from(ST(0), "version")) {
517                lobj = SvRV(ST(0));
518           }
519           else
520                Perl_croak(aTHX_ "lobj is not of type version");
521
522           PUSHs(sv_2mortal(vstringify(lobj)));
523
524           PUTBACK;
525           return;
526      }
527 }
528
529 XS(XS_version_numify)
530 {
531      dVAR;
532      dXSARGS;
533      if (items < 1)
534           Perl_croak(aTHX_ "Usage: version::numify(lobj, ...)");
535      SP -= items;
536      {
537           SV *  lobj;
538
539           if (sv_derived_from(ST(0), "version")) {
540                lobj = SvRV(ST(0));
541           }
542           else
543                Perl_croak(aTHX_ "lobj is not of type version");
544
545           PUSHs(sv_2mortal(vnumify(lobj)));
546
547           PUTBACK;
548           return;
549      }
550 }
551
552 XS(XS_version_normal)
553 {
554      dVAR;
555      dXSARGS;
556      if (items < 1)
557           Perl_croak(aTHX_ "Usage: version::normal(lobj, ...)");
558      SP -= items;
559      {
560           SV *  lobj;
561
562           if (sv_derived_from(ST(0), "version")) {
563                lobj = SvRV(ST(0));
564           }
565           else
566                Perl_croak(aTHX_ "lobj is not of type version");
567
568           PUSHs(sv_2mortal(vnormal(lobj)));
569
570           PUTBACK;
571           return;
572      }
573 }
574
575 XS(XS_version_vcmp)
576 {
577      dVAR;
578      dXSARGS;
579      if (items < 1)
580           Perl_croak(aTHX_ "Usage: version::vcmp(lobj, ...)");
581      SP -= items;
582      {
583           SV *  lobj;
584
585           if (sv_derived_from(ST(0), "version")) {
586                lobj = SvRV(ST(0));
587           }
588           else
589                Perl_croak(aTHX_ "lobj is not of type version");
590
591           {
592                SV       *rs;
593                SV       *rvs;
594                SV * robj = ST(1);
595                const IV  swap = (IV)SvIV(ST(2));
596
597                if ( ! sv_derived_from(robj, "version") )
598                {
599                     robj = new_version(robj);
600                }
601                rvs = SvRV(robj);
602
603                if ( swap )
604                {
605                     rs = newSViv(vcmp(rvs,lobj));
606                }
607                else
608                {
609                     rs = newSViv(vcmp(lobj,rvs));
610                }
611
612                PUSHs(sv_2mortal(rs));
613           }
614
615           PUTBACK;
616           return;
617      }
618 }
619
620 XS(XS_version_boolean)
621 {
622     dVAR;
623     dXSARGS;
624     if (items < 1)
625         Perl_croak(aTHX_ "Usage: version::boolean(lobj, ...)");
626     SP -= items;
627     if (sv_derived_from(ST(0), "version")) {
628         SV * const lobj = SvRV(ST(0));
629         SV * const rs = newSViv( vcmp(lobj,new_version(newSVpvs("0"))) );
630         PUSHs(sv_2mortal(rs));
631         PUTBACK;
632         return;
633     }
634     else
635         Perl_croak(aTHX_ "lobj is not of type version");
636 }
637
638 XS(XS_version_noop)
639 {
640     dVAR;
641     dXSARGS;
642     if (items < 1)
643         Perl_croak(aTHX_ "Usage: version::noop(lobj, ...)");
644     if (sv_derived_from(ST(0), "version"))
645         Perl_croak(aTHX_ "operation not supported with version object");
646     else
647         Perl_croak(aTHX_ "lobj is not of type version");
648 #ifndef HASATTRIBUTE_NORETURN
649     XSRETURN_EMPTY;
650 #endif
651 }
652
653 XS(XS_version_is_alpha)
654 {
655     dVAR;
656     dXSARGS;
657     if (items != 1)
658         Perl_croak(aTHX_ "Usage: version::is_alpha(lobj)");
659     SP -= items;
660     if (sv_derived_from(ST(0), "version")) {
661         SV * const lobj = ST(0);
662         if ( hv_exists((HV*)SvRV(lobj), "alpha", 5 ) )
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
673 XS(XS_version_qv)
674 {
675     dVAR;
676     dXSARGS;
677     if (items != 1)
678         Perl_croak(aTHX_ "Usage: version::qv(ver)");
679     SP -= items;
680     {
681         SV *    ver = ST(0);
682         if ( !SvVOK(ver) ) { /* only need to do with if not already v-string */
683             SV * const vs = sv_newmortal();
684             char *version;
685             if ( SvNOK(ver) ) /* may get too much accuracy */
686             {
687                 char tbuf[64];
688                 const STRLEN len = my_snprintf(tbuf, sizeof(tbuf), "%.9"NVgf, SvNVX(ver));
689                 version = savepvn(tbuf, len);
690             }
691             else
692             {
693                 version = savesvpv(ver);
694             }
695             (void)scan_version(version,vs,TRUE);
696             Safefree(version);
697
698             PUSHs(vs);
699         }
700         else
701         {
702             PUSHs(sv_2mortal(new_version(ver)));
703         }
704
705         PUTBACK;
706         return;
707     }
708 }
709
710 XS(XS_utf8_is_utf8)
711 {
712      dVAR;
713      dXSARGS;
714      if (items != 1)
715           Perl_croak(aTHX_ "Usage: utf8::is_utf8(sv)");
716      else {
717         const SV * const sv = ST(0);
718             if (SvUTF8(sv))
719                 XSRETURN_YES;
720             else
721                 XSRETURN_NO;
722      }
723      XSRETURN_EMPTY;
724 }
725
726 XS(XS_utf8_valid)
727 {
728      dVAR;
729      dXSARGS;
730      if (items != 1)
731           Perl_croak(aTHX_ "Usage: utf8::valid(sv)");
732     else {
733         SV * const sv = ST(0);
734         STRLEN len;
735         const char * const s = SvPV_const(sv,len);
736         if (!SvUTF8(sv) || is_utf8_string((const U8*)s,len))
737             XSRETURN_YES;
738         else
739             XSRETURN_NO;
740     }
741      XSRETURN_EMPTY;
742 }
743
744 XS(XS_utf8_encode)
745 {
746     dVAR;
747     dXSARGS;
748     if (items != 1)
749         Perl_croak(aTHX_ "Usage: utf8::encode(sv)");
750     sv_utf8_encode(ST(0));
751     XSRETURN_EMPTY;
752 }
753
754 XS(XS_utf8_decode)
755 {
756     dVAR;
757     dXSARGS;
758     if (items != 1)
759         Perl_croak(aTHX_ "Usage: utf8::decode(sv)");
760     else {
761         SV * const sv = ST(0);
762         const bool RETVAL = sv_utf8_decode(sv);
763         ST(0) = boolSV(RETVAL);
764         sv_2mortal(ST(0));
765     }
766     XSRETURN(1);
767 }
768
769 XS(XS_utf8_upgrade)
770 {
771     dVAR;
772     dXSARGS;
773     if (items != 1)
774         Perl_croak(aTHX_ "Usage: utf8::upgrade(sv)");
775     else {
776         SV * const sv = ST(0);
777         STRLEN  RETVAL;
778         dXSTARG;
779
780         RETVAL = sv_utf8_upgrade(sv);
781         XSprePUSH; PUSHi((IV)RETVAL);
782     }
783     XSRETURN(1);
784 }
785
786 XS(XS_utf8_downgrade)
787 {
788     dVAR;
789     dXSARGS;
790     if (items < 1 || items > 2)
791         Perl_croak(aTHX_ "Usage: utf8::downgrade(sv, failok=0)");
792     else {
793         SV * const sv = ST(0);
794         const bool failok = (items < 2) ? 0 : (int)SvIV(ST(1));
795         const bool RETVAL = sv_utf8_downgrade(sv, failok);
796
797         ST(0) = boolSV(RETVAL);
798         sv_2mortal(ST(0));
799     }
800     XSRETURN(1);
801 }
802
803 XS(XS_utf8_native_to_unicode)
804 {
805  dVAR;
806  dXSARGS;
807  const UV uv = SvUV(ST(0));
808
809  if (items > 1)
810      Perl_croak(aTHX_ "Usage: utf8::native_to_unicode(sv)");
811
812  ST(0) = sv_2mortal(newSViv(NATIVE_TO_UNI(uv)));
813  XSRETURN(1);
814 }
815
816 XS(XS_utf8_unicode_to_native)
817 {
818  dVAR;
819  dXSARGS;
820  const UV uv = SvUV(ST(0));
821
822  if (items > 1)
823      Perl_croak(aTHX_ "Usage: utf8::unicode_to_native(sv)");
824
825  ST(0) = sv_2mortal(newSViv(UNI_TO_NATIVE(uv)));
826  XSRETURN(1);
827 }
828
829 XS(XS_Internals_SvREADONLY)     /* This is dangerous stuff. */
830 {
831     dVAR;
832     dXSARGS;
833     SV * const sv = SvRV(ST(0));
834
835     if (items == 1) {
836          if (SvREADONLY(sv))
837              XSRETURN_YES;
838          else
839              XSRETURN_NO;
840     }
841     else if (items == 2) {
842         if (SvTRUE(ST(1))) {
843             SvREADONLY_on(sv);
844             XSRETURN_YES;
845         }
846         else {
847             /* I hope you really know what you are doing. */
848             SvREADONLY_off(sv);
849             XSRETURN_NO;
850         }
851     }
852     XSRETURN_UNDEF; /* Can't happen. */
853 }
854
855 XS(XS_Internals_SvREFCNT)       /* This is dangerous stuff. */
856 {
857     dVAR;
858     dXSARGS;
859     SV * const sv = SvRV(ST(0));
860
861     if (items == 1)
862          XSRETURN_IV(SvREFCNT(sv) - 1); /* Minus the ref created for us. */
863     else if (items == 2) {
864          /* I hope you really know what you are doing. */
865          SvREFCNT(sv) = SvIV(ST(1));
866          XSRETURN_IV(SvREFCNT(sv));
867     }
868     XSRETURN_UNDEF; /* Can't happen. */
869 }
870
871 XS(XS_Internals_hv_clear_placehold)
872 {
873     dVAR;
874     dXSARGS;
875
876     if (items != 1)
877         Perl_croak(aTHX_ "Usage: UNIVERSAL::hv_clear_placeholders(hv)");
878     else {
879         HV * const hv = (HV *) SvRV(ST(0));
880         hv_clear_placeholders(hv);
881         XSRETURN(0);
882     }
883 }
884
885 XS(XS_Regexp_DESTROY)
886 {
887     PERL_UNUSED_CONTEXT;
888     PERL_UNUSED_ARG(cv);
889 }
890
891 XS(XS_PerlIO_get_layers)
892 {
893     dVAR;
894     dXSARGS;
895     if (items < 1 || items % 2 == 0)
896         Perl_croak(aTHX_ "Usage: PerlIO_get_layers(filehandle[,args])");
897 #ifdef USE_PERLIO
898     {
899         SV *    sv;
900         GV *    gv;
901         IO *    io;
902         bool    input = TRUE;
903         bool    details = FALSE;
904
905         if (items > 1) {
906              SV * const *svp;
907              for (svp = MARK + 2; svp <= SP; svp += 2) {
908                   SV * const * const varp = svp;
909                   SV * const * const valp = svp + 1;
910                   STRLEN klen;
911                   const char * const key = SvPV_const(*varp, klen);
912
913                   switch (*key) {
914                   case 'i':
915                        if (klen == 5 && memEQ(key, "input", 5)) {
916                             input = SvTRUE(*valp);
917                             break;
918                        }
919                        goto fail;
920                   case 'o': 
921                        if (klen == 6 && memEQ(key, "output", 6)) {
922                             input = !SvTRUE(*valp);
923                             break;
924                        }
925                        goto fail;
926                   case 'd':
927                        if (klen == 7 && memEQ(key, "details", 7)) {
928                             details = SvTRUE(*valp);
929                             break;
930                        }
931                        goto fail;
932                   default:
933                   fail:
934                        Perl_croak(aTHX_
935                                   "get_layers: unknown argument '%s'",
936                                   key);
937                   }
938              }
939
940              SP -= (items - 1);
941         }
942
943         sv = POPs;
944         gv = (GV*)sv;
945
946         if (!isGV(sv)) {
947              if (SvROK(sv) && isGV(SvRV(sv)))
948                   gv = (GV*)SvRV(sv);
949              else if (SvPOKp(sv))
950                   gv = gv_fetchsv(sv, 0, SVt_PVIO);
951         }
952
953         if (gv && (io = GvIO(gv))) {
954              dTARGET;
955              AV* const av = PerlIO_get_layers(aTHX_ input ?
956                                         IoIFP(io) : IoOFP(io));
957              I32 i;
958              const I32 last = av_len(av);
959              I32 nitem = 0;
960              
961              for (i = last; i >= 0; i -= 3) {
962                   SV * const * const namsvp = av_fetch(av, i - 2, FALSE);
963                   SV * const * const argsvp = av_fetch(av, i - 1, FALSE);
964                   SV * const * const flgsvp = av_fetch(av, i,     FALSE);
965
966                   const bool namok = namsvp && *namsvp && SvPOK(*namsvp);
967                   const bool argok = argsvp && *argsvp && SvPOK(*argsvp);
968                   const bool flgok = flgsvp && *flgsvp && SvIOK(*flgsvp);
969
970                   if (details) {
971                        XPUSHs(namok
972                               ? newSVpvn(SvPVX_const(*namsvp), SvCUR(*namsvp))
973                               : &PL_sv_undef);
974                        XPUSHs(argok
975                               ? newSVpvn(SvPVX_const(*argsvp), SvCUR(*argsvp))
976                               : &PL_sv_undef);
977                        if (flgok)
978                             XPUSHi(SvIVX(*flgsvp));
979                        else
980                             XPUSHs(&PL_sv_undef);
981                        nitem += 3;
982                   }
983                   else {
984                        if (namok && argok)
985                             XPUSHs(Perl_newSVpvf(aTHX_ "%"SVf"(%"SVf")",
986                                                  (void*)*namsvp,
987                                                  (void*)*argsvp));
988                        else if (namok)
989                             XPUSHs(Perl_newSVpvf(aTHX_ "%"SVf,
990                                                  (void*)*namsvp));
991                        else
992                             XPUSHs(&PL_sv_undef);
993                        nitem++;
994                        if (flgok) {
995                             const IV flags = SvIVX(*flgsvp);
996
997                             if (flags & PERLIO_F_UTF8) {
998                                  XPUSHs(newSVpvs("utf8"));
999                                  nitem++;
1000                             }
1001                        }
1002                   }
1003              }
1004
1005              SvREFCNT_dec(av);
1006
1007              XSRETURN(nitem);
1008         }
1009     }
1010 #endif
1011
1012     XSRETURN(0);
1013 }
1014
1015 XS(XS_Internals_hash_seed)
1016 {
1017     dVAR;
1018     /* Using dXSARGS would also have dITEM and dSP,
1019      * which define 2 unused local variables.  */
1020     dAXMARK;
1021     PERL_UNUSED_ARG(cv);
1022     PERL_UNUSED_VAR(mark);
1023     XSRETURN_UV(PERL_HASH_SEED);
1024 }
1025
1026 XS(XS_Internals_rehash_seed)
1027 {
1028     dVAR;
1029     /* Using dXSARGS would also have dITEM and dSP,
1030      * which define 2 unused local variables.  */
1031     dAXMARK;
1032     PERL_UNUSED_ARG(cv);
1033     PERL_UNUSED_VAR(mark);
1034     XSRETURN_UV(PL_rehash_seed);
1035 }
1036
1037 XS(XS_Internals_HvREHASH)       /* Subject to change  */
1038 {
1039     dVAR;
1040     dXSARGS;
1041     if (SvROK(ST(0))) {
1042         const HV * const hv = (HV *) SvRV(ST(0));
1043         if (items == 1 && SvTYPE(hv) == SVt_PVHV) {
1044             if (HvREHASH(hv))
1045                 XSRETURN_YES;
1046             else
1047                 XSRETURN_NO;
1048         }
1049     }
1050     Perl_croak(aTHX_ "Internals::HvREHASH $hashref");
1051 }
1052
1053 XS(XS_Internals_inc_sub_generation)
1054 {
1055     dVAR;
1056     /* Using dXSARGS would also have dITEM and dSP,
1057      * which define 2 unused local variables.  */
1058     dAXMARK;
1059     PERL_UNUSED_ARG(cv);
1060     PERL_UNUSED_VAR(mark);
1061     ++PL_sub_generation;
1062     XSRETURN_EMPTY;
1063 }
1064
1065 /*
1066  * Local variables:
1067  * c-indentation-style: bsd
1068  * c-basic-offset: 4
1069  * indent-tabs-mode: t
1070  * End:
1071  *
1072  * ex: set ts=8 sts=4 sw=4 noet:
1073  */