xref: /openbsd-src/gnu/usr.bin/perl/universal.c (revision d13be5d47e4149db2549a9828e244d59dbc43f15)
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 seperate 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 #ifdef USE_PERLIO
33 #include "perliol.h" /* For the PERLIO_F_XXX */
34 #endif
35 
36 static HV *
37 S_get_isa_hash(pTHX_ HV *const stash)
38 {
39     dVAR;
40     struct mro_meta *const meta = HvMROMETA(stash);
41 
42     PERL_ARGS_ASSERT_GET_ISA_HASH;
43 
44     if (!meta->isa) {
45 	AV *const isa = mro_get_linear_isa(stash);
46 	if (!meta->isa) {
47 	    HV *const isa_hash = newHV();
48 	    /* Linearisation didn't build it for us, so do it here.  */
49 	    SV *const *svp = AvARRAY(isa);
50 	    SV *const *const svp_end = svp + AvFILLp(isa) + 1;
51 	    const HEK *const canon_name = HvNAME_HEK(stash);
52 
53 	    while (svp < svp_end) {
54 		(void) hv_store_ent(isa_hash, *svp++, &PL_sv_undef, 0);
55 	    }
56 
57 	    (void) hv_common(isa_hash, NULL, HEK_KEY(canon_name),
58 			     HEK_LEN(canon_name), HEK_FLAGS(canon_name),
59 			     HV_FETCH_ISSTORE, &PL_sv_undef,
60 			     HEK_HASH(canon_name));
61 	    (void) hv_store(isa_hash, "UNIVERSAL", 9, &PL_sv_undef, 0);
62 
63 	    SvREADONLY_on(isa_hash);
64 
65 	    meta->isa = isa_hash;
66 	}
67     }
68     return meta->isa;
69 }
70 
71 /*
72  * Contributed by Graham Barr  <Graham.Barr@tiuk.ti.com>
73  * The main guts of traverse_isa was actually copied from gv_fetchmeth
74  */
75 
76 STATIC bool
77 S_isa_lookup(pTHX_ HV *stash, const char * const name)
78 {
79     dVAR;
80     const struct mro_meta *const meta = HvMROMETA(stash);
81     HV *const isa = meta->isa ? meta->isa : S_get_isa_hash(aTHX_ stash);
82     STRLEN len = strlen(name);
83     const HV *our_stash;
84 
85     PERL_ARGS_ASSERT_ISA_LOOKUP;
86 
87     if (hv_common(isa, NULL, name, len, 0 /* No "UTF-8" flag possible with only
88 					     a char * argument*/,
89 		  HV_FETCH_ISEXISTS, NULL, 0)) {
90 	/* Direct name lookup worked.  */
91 	return TRUE;
92     }
93 
94     /* A stash/class can go by many names (ie. User == main::User), so
95        we use the name in the stash itself, which is canonical.  */
96     our_stash = gv_stashpvn(name, len, 0);
97 
98     if (our_stash) {
99 	HEK *const canon_name = HvNAME_HEK(our_stash);
100 
101 	if (hv_common(isa, NULL, HEK_KEY(canon_name), HEK_LEN(canon_name),
102 		      HEK_FLAGS(canon_name),
103 		      HV_FETCH_ISEXISTS, NULL, HEK_HASH(canon_name))) {
104 	    return TRUE;
105 	}
106     }
107 
108     return FALSE;
109 }
110 
111 /*
112 =head1 SV Manipulation Functions
113 
114 =for apidoc sv_derived_from
115 
116 Returns a boolean indicating whether the SV is derived from the specified class
117 I<at the C level>.  To check derivation at the Perl level, call C<isa()> as a
118 normal Perl method.
119 
120 =cut
121 */
122 
123 bool
124 Perl_sv_derived_from(pTHX_ SV *sv, const char *const name)
125 {
126     dVAR;
127     HV *stash;
128 
129     PERL_ARGS_ASSERT_SV_DERIVED_FROM;
130 
131     SvGETMAGIC(sv);
132 
133     if (SvROK(sv)) {
134 	const char *type;
135         sv = SvRV(sv);
136         type = sv_reftype(sv,0);
137 	if (type && strEQ(type,name))
138 	    return TRUE;
139 	stash = SvOBJECT(sv) ? SvSTASH(sv) : NULL;
140     }
141     else {
142         stash = gv_stashsv(sv, 0);
143     }
144 
145     return stash ? isa_lookup(stash, name) : FALSE;
146 }
147 
148 /*
149 =for apidoc sv_does
150 
151 Returns a boolean indicating whether the SV performs a specific, named role.
152 The SV can be a Perl object or the name of a Perl class.
153 
154 =cut
155 */
156 
157 #include "XSUB.h"
158 
159 bool
160 Perl_sv_does(pTHX_ SV *sv, const char *const name)
161 {
162     const char *classname;
163     bool does_it;
164     SV *methodname;
165     dSP;
166 
167     PERL_ARGS_ASSERT_SV_DOES;
168 
169     ENTER;
170     SAVETMPS;
171 
172     SvGETMAGIC(sv);
173 
174     if (!SvOK(sv) || !(SvROK(sv) || (SvPOK(sv) && SvCUR(sv))
175 	    || (SvGMAGICAL(sv) && SvPOKp(sv) && SvCUR(sv)))) {
176 	LEAVE;
177 	return FALSE;
178     }
179 
180     if (sv_isobject(sv)) {
181 	classname = sv_reftype(SvRV(sv),TRUE);
182     } else {
183 	classname = SvPV_nolen(sv);
184     }
185 
186     if (strEQ(name,classname)) {
187 	LEAVE;
188 	return TRUE;
189     }
190 
191     PUSHMARK(SP);
192     XPUSHs(sv);
193     mXPUSHs(newSVpv(name, 0));
194     PUTBACK;
195 
196     methodname = newSVpvs_flags("isa", SVs_TEMP);
197     /* ugly hack: use the SvSCREAM flag so S_method_common
198      * can figure out we're calling DOES() and not isa(),
199      * and report eventual errors correctly. --rgs */
200     SvSCREAM_on(methodname);
201     call_sv(methodname, G_SCALAR | G_METHOD);
202     SPAGAIN;
203 
204     does_it = SvTRUE( TOPs );
205     FREETMPS;
206     LEAVE;
207 
208     return does_it;
209 }
210 
211 PERL_XS_EXPORT_C void XS_UNIVERSAL_isa(pTHX_ CV *cv);
212 PERL_XS_EXPORT_C void XS_UNIVERSAL_can(pTHX_ CV *cv);
213 PERL_XS_EXPORT_C void XS_UNIVERSAL_DOES(pTHX_ CV *cv);
214 PERL_XS_EXPORT_C void XS_UNIVERSAL_VERSION(pTHX_ CV *cv);
215 XS(XS_version_new);
216 XS(XS_version_stringify);
217 XS(XS_version_numify);
218 XS(XS_version_normal);
219 XS(XS_version_vcmp);
220 XS(XS_version_boolean);
221 #ifdef HASATTRIBUTE_NORETURN
222 XS(XS_version_noop) __attribute__noreturn__;
223 #else
224 XS(XS_version_noop);
225 #endif
226 XS(XS_version_is_alpha);
227 XS(XS_version_qv);
228 XS(XS_version_is_qv);
229 XS(XS_utf8_is_utf8);
230 XS(XS_utf8_valid);
231 XS(XS_utf8_encode);
232 XS(XS_utf8_decode);
233 XS(XS_utf8_upgrade);
234 XS(XS_utf8_downgrade);
235 XS(XS_utf8_unicode_to_native);
236 XS(XS_utf8_native_to_unicode);
237 XS(XS_Internals_SvREADONLY);
238 XS(XS_Internals_SvREFCNT);
239 XS(XS_Internals_hv_clear_placehold);
240 XS(XS_PerlIO_get_layers);
241 XS(XS_Internals_hash_seed);
242 XS(XS_Internals_rehash_seed);
243 XS(XS_Internals_HvREHASH);
244 XS(XS_re_is_regexp);
245 XS(XS_re_regname);
246 XS(XS_re_regnames);
247 XS(XS_re_regnames_count);
248 XS(XS_re_regexp_pattern);
249 XS(XS_Tie_Hash_NamedCapture_FETCH);
250 XS(XS_Tie_Hash_NamedCapture_STORE);
251 XS(XS_Tie_Hash_NamedCapture_DELETE);
252 XS(XS_Tie_Hash_NamedCapture_CLEAR);
253 XS(XS_Tie_Hash_NamedCapture_EXISTS);
254 XS(XS_Tie_Hash_NamedCapture_FIRSTK);
255 XS(XS_Tie_Hash_NamedCapture_NEXTK);
256 XS(XS_Tie_Hash_NamedCapture_SCALAR);
257 XS(XS_Tie_Hash_NamedCapture_flags);
258 
259 void
260 Perl_boot_core_UNIVERSAL(pTHX)
261 {
262     dVAR;
263     static const char file[] = __FILE__;
264 
265     newXS("UNIVERSAL::isa",             XS_UNIVERSAL_isa,         file);
266     newXS("UNIVERSAL::can",             XS_UNIVERSAL_can,         file);
267     newXS("UNIVERSAL::DOES",            XS_UNIVERSAL_DOES,        file);
268     newXS("UNIVERSAL::VERSION", 	XS_UNIVERSAL_VERSION, 	  file);
269     {
270 	/* register the overloading (type 'A') magic */
271 	PL_amagic_generation++;
272 	/* Make it findable via fetchmethod */
273 	newXS("version::()", XS_version_noop, file);
274 	newXS("version::new", XS_version_new, file);
275 	newXS("version::parse", XS_version_new, file);
276 	newXS("version::(\"\"", XS_version_stringify, file);
277 	newXS("version::stringify", XS_version_stringify, file);
278 	newXS("version::(0+", XS_version_numify, file);
279 	newXS("version::numify", XS_version_numify, file);
280 	newXS("version::normal", XS_version_normal, file);
281 	newXS("version::(cmp", XS_version_vcmp, file);
282 	newXS("version::(<=>", XS_version_vcmp, file);
283 	newXS("version::vcmp", XS_version_vcmp, file);
284 	newXS("version::(bool", XS_version_boolean, file);
285 	newXS("version::boolean", XS_version_boolean, file);
286 	newXS("version::(nomethod", XS_version_noop, file);
287 	newXS("version::noop", XS_version_noop, file);
288 	newXS("version::is_alpha", XS_version_is_alpha, file);
289 	newXS("version::qv", XS_version_qv, file);
290 	newXS("version::declare", XS_version_qv, file);
291 	newXS("version::is_qv", XS_version_is_qv, file);
292     }
293     newXS("utf8::is_utf8", XS_utf8_is_utf8, file);
294     newXS("utf8::valid", XS_utf8_valid, file);
295     newXS("utf8::encode", XS_utf8_encode, file);
296     newXS("utf8::decode", XS_utf8_decode, file);
297     newXS("utf8::upgrade", XS_utf8_upgrade, file);
298     newXS("utf8::downgrade", XS_utf8_downgrade, file);
299     newXS("utf8::native_to_unicode", XS_utf8_native_to_unicode, file);
300     newXS("utf8::unicode_to_native", XS_utf8_unicode_to_native, file);
301     newXSproto("Internals::SvREADONLY",XS_Internals_SvREADONLY, file, "\\[$%@];$");
302     newXSproto("Internals::SvREFCNT",XS_Internals_SvREFCNT, file, "\\[$%@];$");
303     newXSproto("Internals::hv_clear_placeholders",
304                XS_Internals_hv_clear_placehold, file, "\\%");
305     newXSproto("PerlIO::get_layers",
306                XS_PerlIO_get_layers, file, "*;@");
307     /* Providing a Regexp::DESTROY fixes #21347. See test in t/op/ref.t  */
308     CvFILE(newCONSTSUB(get_hv("Regexp::", GV_ADD), "DESTROY", NULL))
309 	= (char *)file;
310     newXSproto("Internals::hash_seed",XS_Internals_hash_seed, file, "");
311     newXSproto("Internals::rehash_seed",XS_Internals_rehash_seed, file, "");
312     newXSproto("Internals::HvREHASH", XS_Internals_HvREHASH, file, "\\%");
313     newXSproto("re::is_regexp", XS_re_is_regexp, file, "$");
314     newXSproto("re::regname", XS_re_regname, file, ";$$");
315     newXSproto("re::regnames", XS_re_regnames, file, ";$");
316     newXSproto("re::regnames_count", XS_re_regnames_count, file, "");
317     newXSproto("re::regexp_pattern", XS_re_regexp_pattern, file, "$");
318     newXS("Tie::Hash::NamedCapture::FETCH", XS_Tie_Hash_NamedCapture_FETCH, file);
319     newXS("Tie::Hash::NamedCapture::STORE", XS_Tie_Hash_NamedCapture_STORE, file);
320     newXS("Tie::Hash::NamedCapture::DELETE", XS_Tie_Hash_NamedCapture_DELETE, file);
321     newXS("Tie::Hash::NamedCapture::CLEAR", XS_Tie_Hash_NamedCapture_CLEAR, file);
322     newXS("Tie::Hash::NamedCapture::EXISTS", XS_Tie_Hash_NamedCapture_EXISTS, file);
323     newXS("Tie::Hash::NamedCapture::FIRSTKEY", XS_Tie_Hash_NamedCapture_FIRSTK, file);
324     newXS("Tie::Hash::NamedCapture::NEXTKEY", XS_Tie_Hash_NamedCapture_NEXTK, file);
325     newXS("Tie::Hash::NamedCapture::SCALAR", XS_Tie_Hash_NamedCapture_SCALAR, file);
326     newXS("Tie::Hash::NamedCapture::flags", XS_Tie_Hash_NamedCapture_flags, file);
327 }
328 
329 /*
330 =for apidoc croak_xs_usage
331 
332 A specialised variant of C<croak()> for emitting the usage message for xsubs
333 
334     croak_xs_usage(cv, "eee_yow");
335 
336 works out the package name and subroutine name from C<cv>, and then calls
337 C<croak()>. Hence if C<cv> is C<&ouch::awk>, it would call C<croak> as:
338 
339     Perl_croak(aTHX_ "Usage %s::%s(%s)", "ouch" "awk", "eee_yow");
340 
341 =cut
342 */
343 
344 void
345 Perl_croak_xs_usage(pTHX_ const CV *const cv, const char *const params)
346 {
347     const GV *const gv = CvGV(cv);
348 
349     PERL_ARGS_ASSERT_CROAK_XS_USAGE;
350 
351     if (gv) {
352 	const char *const gvname = GvNAME(gv);
353 	const HV *const stash = GvSTASH(gv);
354 	const char *const hvname = stash ? HvNAME_get(stash) : NULL;
355 
356 	if (hvname)
357 	    Perl_croak(aTHX_ "Usage: %s::%s(%s)", hvname, gvname, params);
358 	else
359 	    Perl_croak(aTHX_ "Usage: %s(%s)", gvname, params);
360     } else {
361 	/* Pants. I don't think that it should be possible to get here. */
362 	Perl_croak(aTHX_ "Usage: CODE(0x%"UVxf")(%s)", PTR2UV(cv), params);
363     }
364 }
365 
366 XS(XS_UNIVERSAL_isa)
367 {
368     dVAR;
369     dXSARGS;
370 
371     if (items != 2)
372 	croak_xs_usage(cv, "reference, kind");
373     else {
374 	SV * const sv = ST(0);
375 	const char *name;
376 
377 	SvGETMAGIC(sv);
378 
379 	if (!SvOK(sv) || !(SvROK(sv) || (SvPOK(sv) && SvCUR(sv))
380 		    || (SvGMAGICAL(sv) && SvPOKp(sv) && SvCUR(sv))))
381 	    XSRETURN_UNDEF;
382 
383 	name = SvPV_nolen_const(ST(1));
384 
385 	ST(0) = boolSV(sv_derived_from(sv, name));
386 	XSRETURN(1);
387     }
388 }
389 
390 XS(XS_UNIVERSAL_can)
391 {
392     dVAR;
393     dXSARGS;
394     SV   *sv;
395     const char *name;
396     SV   *rv;
397     HV   *pkg = NULL;
398 
399     if (items != 2)
400 	croak_xs_usage(cv, "object-ref, method");
401 
402     sv = ST(0);
403 
404     SvGETMAGIC(sv);
405 
406     if (!SvOK(sv) || !(SvROK(sv) || (SvPOK(sv) && SvCUR(sv))
407 		|| (SvGMAGICAL(sv) && SvPOKp(sv) && SvCUR(sv))))
408 	XSRETURN_UNDEF;
409 
410     name = SvPV_nolen_const(ST(1));
411     rv = &PL_sv_undef;
412 
413     if (SvROK(sv)) {
414         sv = MUTABLE_SV(SvRV(sv));
415         if (SvOBJECT(sv))
416             pkg = SvSTASH(sv);
417     }
418     else {
419         pkg = gv_stashsv(sv, 0);
420     }
421 
422     if (pkg) {
423 	GV * const gv = gv_fetchmethod_autoload(pkg, name, FALSE);
424         if (gv && isGV(gv))
425 	    rv = sv_2mortal(newRV(MUTABLE_SV(GvCV(gv))));
426     }
427 
428     ST(0) = rv;
429     XSRETURN(1);
430 }
431 
432 XS(XS_UNIVERSAL_DOES)
433 {
434     dVAR;
435     dXSARGS;
436     PERL_UNUSED_ARG(cv);
437 
438     if (items != 2)
439 	Perl_croak(aTHX_ "Usage: invocant->DOES(kind)");
440     else {
441 	SV * const sv = ST(0);
442 	const char *name;
443 
444 	name = SvPV_nolen_const(ST(1));
445 	if (sv_does( sv, name ))
446 	    XSRETURN_YES;
447 
448 	XSRETURN_NO;
449     }
450 }
451 
452 XS(XS_UNIVERSAL_VERSION)
453 {
454     dVAR;
455     dXSARGS;
456     HV *pkg;
457     GV **gvp;
458     GV *gv;
459     SV *sv;
460     const char *undef;
461     PERL_UNUSED_ARG(cv);
462 
463     if (SvROK(ST(0))) {
464         sv = MUTABLE_SV(SvRV(ST(0)));
465         if (!SvOBJECT(sv))
466             Perl_croak(aTHX_ "Cannot find version of an unblessed reference");
467         pkg = SvSTASH(sv);
468     }
469     else {
470         pkg = gv_stashsv(ST(0), 0);
471     }
472 
473     gvp = pkg ? (GV**)hv_fetchs(pkg, "VERSION", FALSE) : NULL;
474 
475     if (gvp && isGV(gv = *gvp) && (sv = GvSV(gv)) && SvOK(sv)) {
476         SV * const nsv = sv_newmortal();
477         sv_setsv(nsv, sv);
478         sv = nsv;
479 	if ( !sv_derived_from(sv, "version"))
480 	    upg_version(sv, FALSE);
481         undef = NULL;
482     }
483     else {
484         sv = &PL_sv_undef;
485         undef = "(undef)";
486     }
487 
488     if (items > 1) {
489 	SV *req = ST(1);
490 
491 	if (undef) {
492 	    if (pkg) {
493 		const char * const name = HvNAME_get(pkg);
494 		Perl_croak(aTHX_
495 			   "%s does not define $%s::VERSION--version check failed",
496 			   name, name);
497 	    } else {
498 		Perl_croak(aTHX_
499 			     "%s defines neither package nor VERSION--version check failed",
500 			     SvPVx_nolen_const(ST(0)) );
501 	     }
502 	}
503 
504 	if ( !sv_derived_from(req, "version")) {
505 	    /* req may very well be R/O, so create a new object */
506 	    req = sv_2mortal( new_version(req) );
507 	}
508 
509 	if ( vcmp( req, sv ) > 0 ) {
510 	    if ( hv_exists(MUTABLE_HV(SvRV(req)), "qv", 2 ) ) {
511 		Perl_croak(aTHX_ "%s version %"SVf" required--"
512 		       "this is only version %"SVf"", HvNAME_get(pkg),
513 		       SVfARG(vnormal(req)),
514 		       SVfARG(vnormal(sv)));
515 	    } else {
516 		Perl_croak(aTHX_ "%s version %"SVf" required--"
517 		       "this is only version %"SVf"", HvNAME_get(pkg),
518 		       SVfARG(vstringify(req)),
519 		       SVfARG(vstringify(sv)));
520 	    }
521 	}
522 
523     }
524 
525     if ( SvOK(sv) && sv_derived_from(sv, "version") ) {
526 	ST(0) = vstringify(sv);
527     } else {
528 	ST(0) = sv;
529     }
530 
531     XSRETURN(1);
532 }
533 
534 XS(XS_version_new)
535 {
536     dVAR;
537     dXSARGS;
538     if (items > 3)
539 	croak_xs_usage(cv, "class, version");
540     SP -= items;
541     {
542         SV *vs = ST(1);
543 	SV *rv;
544 	const char * const classname =
545 	    sv_isobject(ST(0)) /* get the class if called as an object method */
546 		? HvNAME(SvSTASH(SvRV(ST(0))))
547 		: (char *)SvPV_nolen(ST(0));
548 
549 	if ( items == 1 || ! SvOK(vs) ) { /* no param or explicit undef */
550 	    /* create empty object */
551 	    vs = sv_newmortal();
552 	    sv_setpvs(vs, "0");
553 	}
554 	else if ( items == 3 ) {
555 	    vs = sv_newmortal();
556 	    Perl_sv_setpvf(aTHX_ vs,"v%s",SvPV_nolen_const(ST(2)));
557 	}
558 
559 	rv = new_version(vs);
560 	if ( strcmp(classname,"version") != 0 ) /* inherited new() */
561 	    sv_bless(rv, gv_stashpv(classname, GV_ADD));
562 
563 	mPUSHs(rv);
564 	PUTBACK;
565 	return;
566     }
567 }
568 
569 XS(XS_version_stringify)
570 {
571      dVAR;
572      dXSARGS;
573      if (items < 1)
574 	 croak_xs_usage(cv, "lobj, ...");
575      SP -= items;
576      {
577 	  SV *	lobj;
578 
579 	  if (sv_derived_from(ST(0), "version")) {
580 	       lobj = SvRV(ST(0));
581 	  }
582 	  else
583 	       Perl_croak(aTHX_ "lobj is not of type version");
584 
585 	  mPUSHs(vstringify(lobj));
586 
587 	  PUTBACK;
588 	  return;
589      }
590 }
591 
592 XS(XS_version_numify)
593 {
594      dVAR;
595      dXSARGS;
596      if (items < 1)
597 	 croak_xs_usage(cv, "lobj, ...");
598      SP -= items;
599      {
600 	  SV *	lobj;
601 
602 	  if (sv_derived_from(ST(0), "version")) {
603 	       lobj = SvRV(ST(0));
604 	  }
605 	  else
606 	       Perl_croak(aTHX_ "lobj is not of type version");
607 
608 	  mPUSHs(vnumify(lobj));
609 
610 	  PUTBACK;
611 	  return;
612      }
613 }
614 
615 XS(XS_version_normal)
616 {
617      dVAR;
618      dXSARGS;
619      if (items < 1)
620 	 croak_xs_usage(cv, "lobj, ...");
621      SP -= items;
622      {
623 	  SV *	lobj;
624 
625 	  if (sv_derived_from(ST(0), "version")) {
626 	       lobj = SvRV(ST(0));
627 	  }
628 	  else
629 	       Perl_croak(aTHX_ "lobj is not of type version");
630 
631 	  mPUSHs(vnormal(lobj));
632 
633 	  PUTBACK;
634 	  return;
635      }
636 }
637 
638 XS(XS_version_vcmp)
639 {
640      dVAR;
641      dXSARGS;
642      if (items < 1)
643 	 croak_xs_usage(cv, "lobj, ...");
644      SP -= items;
645      {
646 	  SV *	lobj;
647 
648 	  if (sv_derived_from(ST(0), "version")) {
649 	       lobj = SvRV(ST(0));
650 	  }
651 	  else
652 	       Perl_croak(aTHX_ "lobj is not of type version");
653 
654 	  {
655 	       SV	*rs;
656 	       SV	*rvs;
657 	       SV * robj = ST(1);
658 	       const IV	 swap = (IV)SvIV(ST(2));
659 
660 	       if ( ! sv_derived_from(robj, "version") )
661 	       {
662 		    robj = new_version(SvOK(robj) ? robj : newSVpvs("0"));
663 	       }
664 	       rvs = SvRV(robj);
665 
666 	       if ( swap )
667 	       {
668 		    rs = newSViv(vcmp(rvs,lobj));
669 	       }
670 	       else
671 	       {
672 		    rs = newSViv(vcmp(lobj,rvs));
673 	       }
674 
675 	       mPUSHs(rs);
676 	  }
677 
678 	  PUTBACK;
679 	  return;
680      }
681 }
682 
683 XS(XS_version_boolean)
684 {
685     dVAR;
686     dXSARGS;
687     if (items < 1)
688 	croak_xs_usage(cv, "lobj, ...");
689     SP -= items;
690     if (sv_derived_from(ST(0), "version")) {
691 	SV * const lobj = SvRV(ST(0));
692 	SV * const rs = newSViv( vcmp(lobj,new_version(newSVpvs("0"))) );
693 	mPUSHs(rs);
694 	PUTBACK;
695 	return;
696     }
697     else
698 	Perl_croak(aTHX_ "lobj is not of type version");
699 }
700 
701 XS(XS_version_noop)
702 {
703     dVAR;
704     dXSARGS;
705     if (items < 1)
706 	croak_xs_usage(cv, "lobj, ...");
707     if (sv_derived_from(ST(0), "version"))
708 	Perl_croak(aTHX_ "operation not supported with version object");
709     else
710 	Perl_croak(aTHX_ "lobj is not of type version");
711 #ifndef HASATTRIBUTE_NORETURN
712     XSRETURN_EMPTY;
713 #endif
714 }
715 
716 XS(XS_version_is_alpha)
717 {
718     dVAR;
719     dXSARGS;
720     if (items != 1)
721 	croak_xs_usage(cv, "lobj");
722     SP -= items;
723     if (sv_derived_from(ST(0), "version")) {
724 	SV * const lobj = ST(0);
725 	if ( hv_exists(MUTABLE_HV(SvRV(lobj)), "alpha", 5 ) )
726 	    XSRETURN_YES;
727 	else
728 	    XSRETURN_NO;
729 	PUTBACK;
730 	return;
731     }
732     else
733 	Perl_croak(aTHX_ "lobj is not of type version");
734 }
735 
736 XS(XS_version_qv)
737 {
738     dVAR;
739     dXSARGS;
740     PERL_UNUSED_ARG(cv);
741     SP -= items;
742     {
743 	SV * ver = ST(0);
744 	SV * rv;
745 	const char * classname = "";
746 	if ( items == 2 && SvOK(ST(1)) ) {
747 	    /* getting called as object or class method */
748 	    ver = ST(1);
749 	    classname =
750 		sv_isobject(ST(0)) /* class called as an object method */
751 		    ? HvNAME_get(SvSTASH(SvRV(ST(0))))
752 		    : (char *)SvPV_nolen(ST(0));
753 	}
754 	if ( !SvVOK(ver) ) { /* not already a v-string */
755 	    rv = sv_newmortal();
756 	    sv_setsv(rv,ver); /* make a duplicate */
757 	    upg_version(rv, TRUE);
758 	} else {
759 	    rv = sv_2mortal(new_version(ver));
760 	}
761 	if ( items == 2 && strcmp(classname,"version") ) { /* inherited new() */
762 	    sv_bless(rv, gv_stashpv(classname, GV_ADD));
763 	}
764 	PUSHs(rv);
765     }
766     PUTBACK;
767     return;
768 }
769 
770 XS(XS_version_is_qv)
771 {
772     dVAR;
773     dXSARGS;
774     if (items != 1)
775 	croak_xs_usage(cv, "lobj");
776     SP -= items;
777     if (sv_derived_from(ST(0), "version")) {
778 	SV * const lobj = ST(0);
779 	if ( hv_exists(MUTABLE_HV(SvRV(lobj)), "qv", 2 ) )
780 	    XSRETURN_YES;
781 	else
782 	    XSRETURN_NO;
783 	PUTBACK;
784 	return;
785     }
786     else
787 	Perl_croak(aTHX_ "lobj is not of type version");
788 }
789 
790 XS(XS_utf8_is_utf8)
791 {
792      dVAR;
793      dXSARGS;
794      if (items != 1)
795 	 croak_xs_usage(cv, "sv");
796      else {
797 	SV * const sv = ST(0);
798 	SvGETMAGIC(sv);
799 	    if (SvUTF8(sv))
800 		XSRETURN_YES;
801 	    else
802 		XSRETURN_NO;
803      }
804      XSRETURN_EMPTY;
805 }
806 
807 XS(XS_utf8_valid)
808 {
809      dVAR;
810      dXSARGS;
811      if (items != 1)
812 	 croak_xs_usage(cv, "sv");
813     else {
814 	SV * const sv = ST(0);
815 	STRLEN len;
816 	const char * const s = SvPV_const(sv,len);
817 	if (!SvUTF8(sv) || is_utf8_string((const U8*)s,len))
818 	    XSRETURN_YES;
819 	else
820 	    XSRETURN_NO;
821     }
822      XSRETURN_EMPTY;
823 }
824 
825 XS(XS_utf8_encode)
826 {
827     dVAR;
828     dXSARGS;
829     if (items != 1)
830 	croak_xs_usage(cv, "sv");
831     sv_utf8_encode(ST(0));
832     XSRETURN_EMPTY;
833 }
834 
835 XS(XS_utf8_decode)
836 {
837     dVAR;
838     dXSARGS;
839     if (items != 1)
840 	croak_xs_usage(cv, "sv");
841     else {
842 	SV * const sv = ST(0);
843 	const bool RETVAL = sv_utf8_decode(sv);
844 	ST(0) = boolSV(RETVAL);
845 	sv_2mortal(ST(0));
846     }
847     XSRETURN(1);
848 }
849 
850 XS(XS_utf8_upgrade)
851 {
852     dVAR;
853     dXSARGS;
854     if (items != 1)
855 	croak_xs_usage(cv, "sv");
856     else {
857 	SV * const sv = ST(0);
858 	STRLEN	RETVAL;
859 	dXSTARG;
860 
861 	RETVAL = sv_utf8_upgrade(sv);
862 	XSprePUSH; PUSHi((IV)RETVAL);
863     }
864     XSRETURN(1);
865 }
866 
867 XS(XS_utf8_downgrade)
868 {
869     dVAR;
870     dXSARGS;
871     if (items < 1 || items > 2)
872 	croak_xs_usage(cv, "sv, failok=0");
873     else {
874 	SV * const sv = ST(0);
875         const bool failok = (items < 2) ? 0 : (int)SvIV(ST(1));
876         const bool RETVAL = sv_utf8_downgrade(sv, failok);
877 
878 	ST(0) = boolSV(RETVAL);
879 	sv_2mortal(ST(0));
880     }
881     XSRETURN(1);
882 }
883 
884 XS(XS_utf8_native_to_unicode)
885 {
886  dVAR;
887  dXSARGS;
888  const UV uv = SvUV(ST(0));
889 
890  if (items > 1)
891      croak_xs_usage(cv, "sv");
892 
893  ST(0) = sv_2mortal(newSViv(NATIVE_TO_UNI(uv)));
894  XSRETURN(1);
895 }
896 
897 XS(XS_utf8_unicode_to_native)
898 {
899  dVAR;
900  dXSARGS;
901  const UV uv = SvUV(ST(0));
902 
903  if (items > 1)
904      croak_xs_usage(cv, "sv");
905 
906  ST(0) = sv_2mortal(newSViv(UNI_TO_NATIVE(uv)));
907  XSRETURN(1);
908 }
909 
910 XS(XS_Internals_SvREADONLY)	/* This is dangerous stuff. */
911 {
912     dVAR;
913     dXSARGS;
914     SV * const sv = SvRV(ST(0));
915     PERL_UNUSED_ARG(cv);
916 
917     if (items == 1) {
918 	 if (SvREADONLY(sv))
919 	     XSRETURN_YES;
920 	 else
921 	     XSRETURN_NO;
922     }
923     else if (items == 2) {
924 	if (SvTRUE(ST(1))) {
925 	    SvREADONLY_on(sv);
926 	    XSRETURN_YES;
927 	}
928 	else {
929 	    /* I hope you really know what you are doing. */
930 	    SvREADONLY_off(sv);
931 	    XSRETURN_NO;
932 	}
933     }
934     XSRETURN_UNDEF; /* Can't happen. */
935 }
936 
937 XS(XS_Internals_SvREFCNT)	/* This is dangerous stuff. */
938 {
939     dVAR;
940     dXSARGS;
941     SV * const sv = SvRV(ST(0));
942     PERL_UNUSED_ARG(cv);
943 
944     if (items == 1)
945 	 XSRETURN_IV(SvREFCNT(sv) - 1); /* Minus the ref created for us. */
946     else if (items == 2) {
947          /* I hope you really know what you are doing. */
948 	 SvREFCNT(sv) = SvIV(ST(1));
949 	 XSRETURN_IV(SvREFCNT(sv));
950     }
951     XSRETURN_UNDEF; /* Can't happen. */
952 }
953 
954 XS(XS_Internals_hv_clear_placehold)
955 {
956     dVAR;
957     dXSARGS;
958 
959     if (items != 1)
960 	croak_xs_usage(cv, "hv");
961     else {
962 	HV * const hv = MUTABLE_HV(SvRV(ST(0)));
963 	hv_clear_placeholders(hv);
964 	XSRETURN(0);
965     }
966 }
967 
968 XS(XS_PerlIO_get_layers)
969 {
970     dVAR;
971     dXSARGS;
972     if (items < 1 || items % 2 == 0)
973 	croak_xs_usage(cv, "filehandle[,args]");
974 #ifdef USE_PERLIO
975     {
976 	SV *	sv;
977 	GV *	gv;
978 	IO *	io;
979 	bool	input = TRUE;
980 	bool	details = FALSE;
981 
982 	if (items > 1) {
983 	     SV * const *svp;
984 	     for (svp = MARK + 2; svp <= SP; svp += 2) {
985 		  SV * const * const varp = svp;
986 		  SV * const * const valp = svp + 1;
987 		  STRLEN klen;
988 		  const char * const key = SvPV_const(*varp, klen);
989 
990 		  switch (*key) {
991 		  case 'i':
992 		       if (klen == 5 && memEQ(key, "input", 5)) {
993 			    input = SvTRUE(*valp);
994 			    break;
995 		       }
996 		       goto fail;
997 		  case 'o':
998 		       if (klen == 6 && memEQ(key, "output", 6)) {
999 			    input = !SvTRUE(*valp);
1000 			    break;
1001 		       }
1002 		       goto fail;
1003 		  case 'd':
1004 		       if (klen == 7 && memEQ(key, "details", 7)) {
1005 			    details = SvTRUE(*valp);
1006 			    break;
1007 		       }
1008 		       goto fail;
1009 		  default:
1010 		  fail:
1011 		       Perl_croak(aTHX_
1012 				  "get_layers: unknown argument '%s'",
1013 				  key);
1014 		  }
1015 	     }
1016 
1017 	     SP -= (items - 1);
1018 	}
1019 
1020 	sv = POPs;
1021 	gv = MUTABLE_GV(sv);
1022 
1023 	if (!isGV(sv)) {
1024 	     if (SvROK(sv) && isGV(SvRV(sv)))
1025 		  gv = MUTABLE_GV(SvRV(sv));
1026 	     else if (SvPOKp(sv))
1027 		  gv = gv_fetchsv(sv, 0, SVt_PVIO);
1028 	}
1029 
1030 	if (gv && (io = GvIO(gv))) {
1031 	     AV* const av = PerlIO_get_layers(aTHX_ input ?
1032 					IoIFP(io) : IoOFP(io));
1033 	     I32 i;
1034 	     const I32 last = av_len(av);
1035 	     I32 nitem = 0;
1036 
1037 	     for (i = last; i >= 0; i -= 3) {
1038 		  SV * const * const namsvp = av_fetch(av, i - 2, FALSE);
1039 		  SV * const * const argsvp = av_fetch(av, i - 1, FALSE);
1040 		  SV * const * const flgsvp = av_fetch(av, i,     FALSE);
1041 
1042 		  const bool namok = namsvp && *namsvp && SvPOK(*namsvp);
1043 		  const bool argok = argsvp && *argsvp && SvPOK(*argsvp);
1044 		  const bool flgok = flgsvp && *flgsvp && SvIOK(*flgsvp);
1045 
1046 		  if (details) {
1047 		      /* Indents of 5? Yuck.  */
1048 		      /* We know that PerlIO_get_layers creates a new SV for
1049 			 the name and flags, so we can just take a reference
1050 			 and "steal" it when we free the AV below.  */
1051 		       XPUSHs(namok
1052 			      ? sv_2mortal(SvREFCNT_inc_simple_NN(*namsvp))
1053 			      : &PL_sv_undef);
1054 		       XPUSHs(argok
1055 			      ? newSVpvn_flags(SvPVX_const(*argsvp),
1056 					       SvCUR(*argsvp),
1057 					       (SvUTF8(*argsvp) ? SVf_UTF8 : 0)
1058 					       | SVs_TEMP)
1059 			      : &PL_sv_undef);
1060 		       XPUSHs(flgok
1061 			      ? sv_2mortal(SvREFCNT_inc_simple_NN(*flgsvp))
1062 			      : &PL_sv_undef);
1063 		       nitem += 3;
1064 		  }
1065 		  else {
1066 		       if (namok && argok)
1067 			    XPUSHs(sv_2mortal(Perl_newSVpvf(aTHX_ "%"SVf"(%"SVf")",
1068 						 SVfARG(*namsvp),
1069 						 SVfARG(*argsvp))));
1070 		       else if (namok)
1071 			   XPUSHs(sv_2mortal(SvREFCNT_inc_simple_NN(*namsvp)));
1072 		       else
1073 			    XPUSHs(&PL_sv_undef);
1074 		       nitem++;
1075 		       if (flgok) {
1076 			    const IV flags = SvIVX(*flgsvp);
1077 
1078 			    if (flags & PERLIO_F_UTF8) {
1079 				 XPUSHs(newSVpvs_flags("utf8", SVs_TEMP));
1080 				 nitem++;
1081 			    }
1082 		       }
1083 		  }
1084 	     }
1085 
1086 	     SvREFCNT_dec(av);
1087 
1088 	     XSRETURN(nitem);
1089 	}
1090     }
1091 #endif
1092 
1093     XSRETURN(0);
1094 }
1095 
1096 XS(XS_Internals_hash_seed)
1097 {
1098     dVAR;
1099     /* Using dXSARGS would also have dITEM and dSP,
1100      * which define 2 unused local variables.  */
1101     dAXMARK;
1102     PERL_UNUSED_ARG(cv);
1103     PERL_UNUSED_VAR(mark);
1104     XSRETURN_UV(PERL_HASH_SEED);
1105 }
1106 
1107 XS(XS_Internals_rehash_seed)
1108 {
1109     dVAR;
1110     /* Using dXSARGS would also have dITEM and dSP,
1111      * which define 2 unused local variables.  */
1112     dAXMARK;
1113     PERL_UNUSED_ARG(cv);
1114     PERL_UNUSED_VAR(mark);
1115     XSRETURN_UV(PL_rehash_seed);
1116 }
1117 
1118 XS(XS_Internals_HvREHASH)	/* Subject to change  */
1119 {
1120     dVAR;
1121     dXSARGS;
1122     PERL_UNUSED_ARG(cv);
1123     if (SvROK(ST(0))) {
1124 	const HV * const hv = (const HV *) SvRV(ST(0));
1125 	if (items == 1 && SvTYPE(hv) == SVt_PVHV) {
1126 	    if (HvREHASH(hv))
1127 		XSRETURN_YES;
1128 	    else
1129 		XSRETURN_NO;
1130 	}
1131     }
1132     Perl_croak(aTHX_ "Internals::HvREHASH $hashref");
1133 }
1134 
1135 XS(XS_re_is_regexp)
1136 {
1137     dVAR;
1138     dXSARGS;
1139     PERL_UNUSED_VAR(cv);
1140 
1141     if (items != 1)
1142 	croak_xs_usage(cv, "sv");
1143 
1144     SP -= items;
1145 
1146     if (SvRXOK(ST(0))) {
1147         XSRETURN_YES;
1148     } else {
1149         XSRETURN_NO;
1150     }
1151 }
1152 
1153 XS(XS_re_regnames_count)
1154 {
1155     REGEXP *rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1156     SV * ret;
1157     dVAR;
1158     dXSARGS;
1159 
1160     if (items != 0)
1161 	croak_xs_usage(cv, "");
1162 
1163     SP -= items;
1164 
1165     if (!rx)
1166         XSRETURN_UNDEF;
1167 
1168     ret = CALLREG_NAMED_BUFF_COUNT(rx);
1169 
1170     SPAGAIN;
1171 
1172     if (ret) {
1173         mXPUSHs(ret);
1174         PUTBACK;
1175         return;
1176     } else {
1177         XSRETURN_UNDEF;
1178     }
1179 }
1180 
1181 XS(XS_re_regname)
1182 {
1183     dVAR;
1184     dXSARGS;
1185     REGEXP * rx;
1186     U32 flags;
1187     SV * ret;
1188 
1189     if (items < 1 || items > 2)
1190 	croak_xs_usage(cv, "name[, all ]");
1191 
1192     SP -= items;
1193 
1194     rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1195 
1196     if (!rx)
1197         XSRETURN_UNDEF;
1198 
1199     if (items == 2 && SvTRUE(ST(1))) {
1200         flags = RXapif_ALL;
1201     } else {
1202         flags = RXapif_ONE;
1203     }
1204     ret = CALLREG_NAMED_BUFF_FETCH(rx, ST(0), (flags | RXapif_REGNAME));
1205 
1206     if (ret) {
1207         mXPUSHs(ret);
1208         XSRETURN(1);
1209     }
1210     XSRETURN_UNDEF;
1211 }
1212 
1213 
1214 XS(XS_re_regnames)
1215 {
1216     dVAR;
1217     dXSARGS;
1218     REGEXP * rx;
1219     U32 flags;
1220     SV *ret;
1221     AV *av;
1222     I32 length;
1223     I32 i;
1224     SV **entry;
1225 
1226     if (items > 1)
1227 	croak_xs_usage(cv, "[all]");
1228 
1229     rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1230 
1231     if (!rx)
1232         XSRETURN_UNDEF;
1233 
1234     if (items == 1 && SvTRUE(ST(0))) {
1235         flags = RXapif_ALL;
1236     } else {
1237         flags = RXapif_ONE;
1238     }
1239 
1240     SP -= items;
1241 
1242     ret = CALLREG_NAMED_BUFF_ALL(rx, (flags | RXapif_REGNAMES));
1243 
1244     SPAGAIN;
1245 
1246     SP -= items;
1247 
1248     if (!ret)
1249         XSRETURN_UNDEF;
1250 
1251     av = MUTABLE_AV(SvRV(ret));
1252     length = av_len(av);
1253 
1254     for (i = 0; i <= length; i++) {
1255         entry = av_fetch(av, i, FALSE);
1256 
1257         if (!entry)
1258             Perl_croak(aTHX_ "NULL array element in re::regnames()");
1259 
1260         mXPUSHs(SvREFCNT_inc_simple_NN(*entry));
1261     }
1262 
1263     SvREFCNT_dec(ret);
1264 
1265     PUTBACK;
1266     return;
1267 }
1268 
1269 XS(XS_re_regexp_pattern)
1270 {
1271     dVAR;
1272     dXSARGS;
1273     REGEXP *re;
1274 
1275     if (items != 1)
1276 	croak_xs_usage(cv, "sv");
1277 
1278     SP -= items;
1279 
1280     /*
1281        Checks if a reference is a regex or not. If the parameter is
1282        not a ref, or is not the result of a qr// then returns false
1283        in scalar context and an empty list in list context.
1284        Otherwise in list context it returns the pattern and the
1285        modifiers, in scalar context it returns the pattern just as it
1286        would if the qr// was stringified normally, regardless as
1287        to the class of the variable and any strigification overloads
1288        on the object.
1289     */
1290 
1291     if ((re = SvRX(ST(0)))) /* assign deliberate */
1292     {
1293         /* Housten, we have a regex! */
1294         SV *pattern;
1295         STRLEN left = 0;
1296         char reflags[6];
1297 
1298         if ( GIMME_V == G_ARRAY ) {
1299             /*
1300                we are in list context so stringify
1301                the modifiers that apply. We ignore "negative
1302                modifiers" in this scenario.
1303             */
1304 
1305             const char *fptr = INT_PAT_MODS;
1306             char ch;
1307             U16 match_flags = (U16)((RX_EXTFLAGS(re) & PMf_COMPILETIME)
1308                                     >> RXf_PMf_STD_PMMOD_SHIFT);
1309 
1310             while((ch = *fptr++)) {
1311                 if(match_flags & 1) {
1312                     reflags[left++] = ch;
1313                 }
1314                 match_flags >>= 1;
1315             }
1316 
1317             pattern = newSVpvn_flags(RX_PRECOMP(re),RX_PRELEN(re),
1318 				     (RX_UTF8(re) ? SVf_UTF8 : 0) | SVs_TEMP);
1319 
1320             /* return the pattern and the modifiers */
1321             XPUSHs(pattern);
1322             XPUSHs(newSVpvn_flags(reflags, left, SVs_TEMP));
1323             XSRETURN(2);
1324         } else {
1325             /* Scalar, so use the string that Perl would return */
1326             /* return the pattern in (?msix:..) format */
1327 #if PERL_VERSION >= 11
1328             pattern = sv_2mortal(newSVsv(MUTABLE_SV(re)));
1329 #else
1330             pattern = newSVpvn_flags(RX_WRAPPED(re), RX_WRAPLEN(re),
1331 				     (RX_UTF8(re) ? SVf_UTF8 : 0) | SVs_TEMP);
1332 #endif
1333             XPUSHs(pattern);
1334             XSRETURN(1);
1335         }
1336     } else {
1337         /* It ain't a regexp folks */
1338         if ( GIMME_V == G_ARRAY ) {
1339             /* return the empty list */
1340             XSRETURN_UNDEF;
1341         } else {
1342             /* Because of the (?:..) wrapping involved in a
1343                stringified pattern it is impossible to get a
1344                result for a real regexp that would evaluate to
1345                false. Therefore we can return PL_sv_no to signify
1346                that the object is not a regex, this means that one
1347                can say
1348 
1349                  if (regex($might_be_a_regex) eq '(?:foo)') { }
1350 
1351                and not worry about undefined values.
1352             */
1353             XSRETURN_NO;
1354         }
1355     }
1356     /* NOT-REACHED */
1357 }
1358 
1359 XS(XS_Tie_Hash_NamedCapture_FETCH)
1360 {
1361     dVAR;
1362     dXSARGS;
1363     REGEXP * rx;
1364     U32 flags;
1365     SV * ret;
1366 
1367     if (items != 2)
1368 	croak_xs_usage(cv, "$key, $flags");
1369 
1370     rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1371 
1372     if (!rx || !SvROK(ST(0)))
1373         XSRETURN_UNDEF;
1374 
1375     SP -= items;
1376 
1377     flags = (U32)INT2PTR(IV,SvIV(SvRV(MUTABLE_SV(ST(0)))));
1378     ret = CALLREG_NAMED_BUFF_FETCH(rx, ST(1), flags);
1379 
1380     SPAGAIN;
1381 
1382     if (ret) {
1383         mXPUSHs(ret);
1384         PUTBACK;
1385         return;
1386     }
1387     XSRETURN_UNDEF;
1388 }
1389 
1390 XS(XS_Tie_Hash_NamedCapture_STORE)
1391 {
1392     dVAR;
1393     dXSARGS;
1394     REGEXP * rx;
1395     U32 flags;
1396 
1397     if (items != 3)
1398 	croak_xs_usage(cv, "$key, $value, $flags");
1399 
1400     rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1401 
1402     if (!rx || !SvROK(ST(0))) {
1403         if (!PL_localizing)
1404             Perl_croak(aTHX_ "%s", PL_no_modify);
1405         else
1406             XSRETURN_UNDEF;
1407     }
1408 
1409     SP -= items;
1410 
1411     flags = (U32)INT2PTR(IV,SvIV(SvRV(MUTABLE_SV(ST(0)))));
1412     CALLREG_NAMED_BUFF_STORE(rx,ST(1), ST(2), flags);
1413 }
1414 
1415 XS(XS_Tie_Hash_NamedCapture_DELETE)
1416 {
1417     dVAR;
1418     dXSARGS;
1419     REGEXP * rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1420     U32 flags;
1421 
1422     if (items != 2)
1423 	croak_xs_usage(cv, "$key, $flags");
1424 
1425     if (!rx || !SvROK(ST(0)))
1426         Perl_croak(aTHX_ "%s", PL_no_modify);
1427 
1428     SP -= items;
1429 
1430     flags = (U32)INT2PTR(IV,SvIV(SvRV(MUTABLE_SV(ST(0)))));
1431     CALLREG_NAMED_BUFF_DELETE(rx, ST(1), flags);
1432 }
1433 
1434 XS(XS_Tie_Hash_NamedCapture_CLEAR)
1435 {
1436     dVAR;
1437     dXSARGS;
1438     REGEXP * rx;
1439     U32 flags;
1440 
1441     if (items != 1)
1442 	croak_xs_usage(cv, "$flags");
1443 
1444     rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1445 
1446     if (!rx || !SvROK(ST(0)))
1447         Perl_croak(aTHX_ "%s", PL_no_modify);
1448 
1449     SP -= items;
1450 
1451     flags = (U32)INT2PTR(IV,SvIV(SvRV(MUTABLE_SV(ST(0)))));
1452     CALLREG_NAMED_BUFF_CLEAR(rx, flags);
1453 }
1454 
1455 XS(XS_Tie_Hash_NamedCapture_EXISTS)
1456 {
1457     dVAR;
1458     dXSARGS;
1459     REGEXP * rx;
1460     U32 flags;
1461     SV * ret;
1462 
1463     if (items != 2)
1464 	croak_xs_usage(cv, "$key, $flags");
1465 
1466     rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1467 
1468     if (!rx || !SvROK(ST(0)))
1469         XSRETURN_UNDEF;
1470 
1471     SP -= items;
1472 
1473     flags = (U32)INT2PTR(IV,SvIV(SvRV(MUTABLE_SV(ST(0)))));
1474     ret = CALLREG_NAMED_BUFF_EXISTS(rx, ST(1), flags);
1475 
1476     SPAGAIN;
1477 
1478 	XPUSHs(ret);
1479 	PUTBACK;
1480 	return;
1481 }
1482 
1483 XS(XS_Tie_Hash_NamedCapture_FIRSTK)
1484 {
1485     dVAR;
1486     dXSARGS;
1487     REGEXP * rx;
1488     U32 flags;
1489     SV * ret;
1490 
1491     if (items != 1)
1492 	croak_xs_usage(cv, "");
1493 
1494     rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1495 
1496     if (!rx || !SvROK(ST(0)))
1497         XSRETURN_UNDEF;
1498 
1499     SP -= items;
1500 
1501     flags = (U32)INT2PTR(IV,SvIV(SvRV(MUTABLE_SV(ST(0)))));
1502     ret = CALLREG_NAMED_BUFF_FIRSTKEY(rx, flags);
1503 
1504     SPAGAIN;
1505 
1506     if (ret) {
1507         mXPUSHs(ret);
1508         PUTBACK;
1509     } else {
1510         XSRETURN_UNDEF;
1511     }
1512 
1513 }
1514 
1515 XS(XS_Tie_Hash_NamedCapture_NEXTK)
1516 {
1517     dVAR;
1518     dXSARGS;
1519     REGEXP * rx;
1520     U32 flags;
1521     SV * ret;
1522 
1523     if (items != 2)
1524 	croak_xs_usage(cv, "$lastkey");
1525 
1526     rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1527 
1528     if (!rx || !SvROK(ST(0)))
1529         XSRETURN_UNDEF;
1530 
1531     SP -= items;
1532 
1533     flags = (U32)INT2PTR(IV,SvIV(SvRV(MUTABLE_SV(ST(0)))));
1534     ret = CALLREG_NAMED_BUFF_NEXTKEY(rx, ST(1), flags);
1535 
1536     SPAGAIN;
1537 
1538     if (ret) {
1539         mXPUSHs(ret);
1540     } else {
1541         XSRETURN_UNDEF;
1542     }
1543     PUTBACK;
1544 }
1545 
1546 XS(XS_Tie_Hash_NamedCapture_SCALAR)
1547 {
1548     dVAR;
1549     dXSARGS;
1550     REGEXP * rx;
1551     U32 flags;
1552     SV * ret;
1553 
1554     if (items != 1)
1555 	croak_xs_usage(cv, "");
1556 
1557     rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
1558 
1559     if (!rx || !SvROK(ST(0)))
1560         XSRETURN_UNDEF;
1561 
1562     SP -= items;
1563 
1564     flags = (U32)INT2PTR(IV,SvIV(SvRV(MUTABLE_SV(ST(0)))));
1565     ret = CALLREG_NAMED_BUFF_SCALAR(rx, flags);
1566 
1567     SPAGAIN;
1568 
1569     if (ret) {
1570         mXPUSHs(ret);
1571         PUTBACK;
1572         return;
1573     } else {
1574         XSRETURN_UNDEF;
1575     }
1576 }
1577 
1578 XS(XS_Tie_Hash_NamedCapture_flags)
1579 {
1580     dVAR;
1581     dXSARGS;
1582 
1583     if (items != 0)
1584 	croak_xs_usage(cv, "");
1585 
1586 	mXPUSHu(RXapif_ONE);
1587 	mXPUSHu(RXapif_ALL);
1588 	PUTBACK;
1589 	return;
1590 }
1591 
1592 
1593 /*
1594  * Local variables:
1595  * c-indentation-style: bsd
1596  * c-basic-offset: 4
1597  * indent-tabs-mode: t
1598  * End:
1599  *
1600  * ex: set ts=8 sts=4 sw=4 noet:
1601  */
1602