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