+ XSRETURN_UNDEF; /* Can't happen. */
+}
+
+XS(XS_Internals_SvREFCNT) /* This is dangerous stuff. */
+{
+ dVAR;
+ dXSARGS;
+ SV * const sv = SvRV(ST(0));
+
+ if (items == 1)
+ XSRETURN_IV(SvREFCNT(sv) - 1); /* Minus the ref created for us. */
+ else if (items == 2) {
+ /* I hope you really know what you are doing. */
+ SvREFCNT(sv) = SvIV(ST(1));
+ XSRETURN_IV(SvREFCNT(sv));
+ }
+ XSRETURN_UNDEF; /* Can't happen. */
+}
+
+XS(XS_Internals_hv_clear_placehold)
+{
+ dVAR;
+ dXSARGS;
+
+ if (items != 1)
+ Perl_croak(aTHX_ "Usage: UNIVERSAL::hv_clear_placeholders(hv)");
+ else {
+ HV * const hv = (HV *) SvRV(ST(0));
+ hv_clear_placeholders(hv);
+ XSRETURN(0);
+ }
+}
+
+XS(XS_Regexp_DESTROY)
+{
+ PERL_UNUSED_CONTEXT;
+ PERL_UNUSED_ARG(cv);
+}
+
+XS(XS_PerlIO_get_layers)
+{
+ dVAR;
+ dXSARGS;
+ if (items < 1 || items % 2 == 0)
+ Perl_croak(aTHX_ "Usage: PerlIO_get_layers(filehandle[,args])");
+#ifdef USE_PERLIO
+ {
+ SV * sv;
+ GV * gv;
+ IO * io;
+ bool input = TRUE;
+ bool details = FALSE;
+
+ if (items > 1) {
+ SV * const *svp;
+ for (svp = MARK + 2; svp <= SP; svp += 2) {
+ SV * const * const varp = svp;
+ SV * const * const valp = svp + 1;
+ STRLEN klen;
+ const char * const key = SvPV_const(*varp, klen);
+
+ switch (*key) {
+ case 'i':
+ if (klen == 5 && memEQ(key, "input", 5)) {
+ input = SvTRUE(*valp);
+ break;
+ }
+ goto fail;
+ case 'o':
+ if (klen == 6 && memEQ(key, "output", 6)) {
+ input = !SvTRUE(*valp);
+ break;
+ }
+ goto fail;
+ case 'd':
+ if (klen == 7 && memEQ(key, "details", 7)) {
+ details = SvTRUE(*valp);
+ break;
+ }
+ goto fail;
+ default:
+ fail:
+ Perl_croak(aTHX_
+ "get_layers: unknown argument '%s'",
+ key);
+ }
+ }
+
+ SP -= (items - 1);
+ }
+
+ sv = POPs;
+ gv = (GV*)sv;
+
+ if (!isGV(sv)) {
+ if (SvROK(sv) && isGV(SvRV(sv)))
+ gv = (GV*)SvRV(sv);
+ else if (SvPOKp(sv))
+ gv = gv_fetchsv(sv, 0, SVt_PVIO);
+ }
+
+ if (gv && (io = GvIO(gv))) {
+ dTARGET;
+ AV* const av = PerlIO_get_layers(aTHX_ input ?
+ IoIFP(io) : IoOFP(io));
+ I32 i;
+ const I32 last = av_len(av);
+ I32 nitem = 0;
+
+ for (i = last; i >= 0; i -= 3) {
+ SV * const * const namsvp = av_fetch(av, i - 2, FALSE);
+ SV * const * const argsvp = av_fetch(av, i - 1, FALSE);
+ SV * const * const flgsvp = av_fetch(av, i, FALSE);
+
+ const bool namok = namsvp && *namsvp && SvPOK(*namsvp);
+ const bool argok = argsvp && *argsvp && SvPOK(*argsvp);
+ const bool flgok = flgsvp && *flgsvp && SvIOK(*flgsvp);
+
+ if (details) {
+ XPUSHs(namok
+ ? newSVpvn(SvPVX_const(*namsvp), SvCUR(*namsvp))
+ : &PL_sv_undef);
+ XPUSHs(argok
+ ? newSVpvn(SvPVX_const(*argsvp), SvCUR(*argsvp))
+ : &PL_sv_undef);
+ if (flgok)
+ XPUSHi(SvIVX(*flgsvp));
+ else
+ XPUSHs(&PL_sv_undef);
+ nitem += 3;
+ }
+ else {
+ if (namok && argok)
+ XPUSHs(Perl_newSVpvf(aTHX_ "%"SVf"(%"SVf")",
+ *namsvp, *argsvp));
+ else if (namok)
+ XPUSHs(Perl_newSVpvf(aTHX_ "%"SVf, *namsvp));
+ else
+ XPUSHs(&PL_sv_undef);
+ nitem++;
+ if (flgok) {
+ const IV flags = SvIVX(*flgsvp);
+
+ if (flags & PERLIO_F_UTF8) {
+ XPUSHs(newSVpvs("utf8"));
+ nitem++;
+ }
+ }
+ }
+ }
+
+ SvREFCNT_dec(av);
+
+ XSRETURN(nitem);
+ }
+ }
+#endif
+
+ XSRETURN(0);