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