summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MANIFEST1
-rw-r--r--ext/Tie-Hash-NamedCapture/NamedCapture.pm8
-rw-r--r--ext/Tie-Hash-NamedCapture/NamedCapture.xs134
-rw-r--r--t/op/magic.t10
-rw-r--r--universal.c214
-rw-r--r--vxs.inc2
6 files changed, 200 insertions, 169 deletions
diff --git a/MANIFEST b/MANIFEST
index 4849ed7687..52f683b6bd 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -4363,7 +4363,6 @@ ext/Sys-Hostname/Hostname.pm Sys::Hostname extension Perl module
ext/Sys-Hostname/Hostname.xs Sys::Hostname extension external subroutines
ext/Sys-Hostname/t/Hostname.t See if Sys::Hostname works
ext/Tie-Hash-NamedCapture/NamedCapture.pm Implements %- and %+ behaviour
-ext/Tie-Hash-NamedCapture/NamedCapture.xs Implements %- and %+ behaviour
ext/Tie-Hash-NamedCapture/t/tiehash.t Tests TIEHASH
ext/Tie-Memoize/lib/Tie/Memoize.pm Base class for memoized tied hashes
ext/Tie-Memoize/t/Tie-Memoize.t Test for Tie::Memoize
diff --git a/ext/Tie-Hash-NamedCapture/NamedCapture.pm b/ext/Tie-Hash-NamedCapture/NamedCapture.pm
index fb505f70a9..95f355aa81 100644
--- a/ext/Tie-Hash-NamedCapture/NamedCapture.pm
+++ b/ext/Tie-Hash-NamedCapture/NamedCapture.pm
@@ -1,10 +1,7 @@
use strict;
package Tie::Hash::NamedCapture;
-our $VERSION = "0.11";
-
-require XSLoader;
-XSLoader::load(); # This returns true, which makes require happy.
+our $VERSION = "0.13";
__END__
@@ -41,6 +38,9 @@ The keys of C<%->-like hashes correspond to all buffer names found in the
regular expression; the keys of C<%+>-like hashes list only the names of
buffers that have captured (and that are thus associated to defined values).
+This implementation has been moved into the core executable, but you
+can still load this module for backward compatibility.
+
=head1 SEE ALSO
L<perlreapi>, L<re>, L<perlmodlib/Pragmatic Modules>, L<perlvar/"%+">,
diff --git a/ext/Tie-Hash-NamedCapture/NamedCapture.xs b/ext/Tie-Hash-NamedCapture/NamedCapture.xs
deleted file mode 100644
index a607c10090..0000000000
--- a/ext/Tie-Hash-NamedCapture/NamedCapture.xs
+++ /dev/null
@@ -1,134 +0,0 @@
-#define PERL_NO_GET_CONTEXT /* we want efficiency */
-#include "EXTERN.h"
-#include "perl.h"
-#include "XSUB.h"
-
-/* These are tightly coupled to the RXapif_* flags defined in regexp.h */
-#define UNDEF_FATAL 0x80000
-#define DISCARD 0x40000
-#define EXPECT_SHIFT 24
-#define ACTION_MASK 0x000FF
-
-#define FETCH_ALIAS (RXapif_FETCH | (2 << EXPECT_SHIFT))
-#define STORE_ALIAS (RXapif_STORE | (3 << EXPECT_SHIFT) | UNDEF_FATAL | DISCARD)
-#define DELETE_ALIAS (RXapif_DELETE | (2 << EXPECT_SHIFT) | UNDEF_FATAL)
-#define CLEAR_ALIAS (RXapif_CLEAR | (1 << EXPECT_SHIFT) | UNDEF_FATAL | DISCARD)
-#define EXISTS_ALIAS (RXapif_EXISTS | (2 << EXPECT_SHIFT))
-#define SCALAR_ALIAS (RXapif_SCALAR | (1 << EXPECT_SHIFT))
-
-MODULE = Tie::Hash::NamedCapture PACKAGE = Tie::Hash::NamedCapture
-PROTOTYPES: DISABLE
-
-void
-_tie_it(SV *sv)
- INIT:
- GV * const gv = (GV *)sv;
- HV * const hv = GvHVn(gv);
- SV *rv = newSV_type(SVt_RV);
- const char *gv_name = GvNAME(gv);
- CODE:
- SvRV_set(rv, newSVuv(
- strEQ(gv_name, "-") || strEQ(gv_name, "\003APTURE_ALL")
- ? RXapif_ALL : RXapif_ONE));
- SvROK_on(rv);
- sv_bless(rv, GvSTASH(CvGV(cv)));
-
- sv_unmagic((SV *)hv, PERL_MAGIC_tied);
- sv_magic((SV *)hv, rv, PERL_MAGIC_tied, NULL, 0);
- SvREFCNT_dec(rv); /* As sv_magic increased it by one. */
-
-SV *
-TIEHASH(package, ...)
- const char *package;
- PREINIT:
- UV flag = RXapif_ONE;
- CODE:
- mark += 2;
- while(mark < sp) {
- STRLEN len;
- const char *p = SvPV_const(*mark, len);
- if(memEQs(p, len, "all"))
- flag = SvTRUE(mark[1]) ? RXapif_ALL : RXapif_ONE;
- mark += 2;
- }
- RETVAL = newSV_type(SVt_RV);
- sv_setuv(newSVrv(RETVAL, package), flag);
- OUTPUT:
- RETVAL
-
-void
-FETCH(...)
- ALIAS:
- Tie::Hash::NamedCapture::FETCH = FETCH_ALIAS
- Tie::Hash::NamedCapture::STORE = STORE_ALIAS
- Tie::Hash::NamedCapture::DELETE = DELETE_ALIAS
- Tie::Hash::NamedCapture::CLEAR = CLEAR_ALIAS
- Tie::Hash::NamedCapture::EXISTS = EXISTS_ALIAS
- Tie::Hash::NamedCapture::SCALAR = SCALAR_ALIAS
- PREINIT:
- REGEXP *const rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
- U32 flags;
- SV *ret;
- const U32 action = ix & ACTION_MASK;
- const int expect = ix >> EXPECT_SHIFT;
- PPCODE:
- if (items != expect)
- croak_xs_usage(cv, expect == 2 ? "$key"
- : (expect == 3 ? "$key, $value"
- : ""));
-
- if (!rx || !SvROK(ST(0))) {
- if (ix & UNDEF_FATAL)
- Perl_croak_no_modify();
- else
- XSRETURN_UNDEF;
- }
-
- flags = (U32)SvUV(SvRV(MUTABLE_SV(ST(0))));
-
- PUTBACK;
- ret = RX_ENGINE(rx)->named_buff(aTHX_ (rx), expect >= 2 ? ST(1) : NULL,
- expect >= 3 ? ST(2) : NULL, flags | action);
- SPAGAIN;
-
- if (ix & DISCARD) {
- /* Called with G_DISCARD, so our return stack state is thrown away.
- Hence if we were returned anything, free it immediately. */
- SvREFCNT_dec(ret);
- } else {
- PUSHs(ret ? sv_2mortal(ret) : &PL_sv_undef);
- }
-
-void
-FIRSTKEY(...)
- ALIAS:
- Tie::Hash::NamedCapture::NEXTKEY = 1
- PREINIT:
- REGEXP *const rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
- U32 flags;
- SV *ret;
- const int expect = ix ? 2 : 1;
- const U32 action = ix ? RXapif_NEXTKEY : RXapif_FIRSTKEY;
- PPCODE:
- if (items != expect)
- croak_xs_usage(cv, expect == 2 ? "$lastkey" : "");
-
- if (!rx || !SvROK(ST(0)))
- XSRETURN_UNDEF;
-
- flags = (U32)SvUV(SvRV(MUTABLE_SV(ST(0))));
-
- PUTBACK;
- ret = RX_ENGINE(rx)->named_buff_iter(aTHX_ (rx),
- expect >= 2 ? ST(1) : NULL,
- flags | action);
- SPAGAIN;
-
- PUSHs(ret ? sv_2mortal(ret) : &PL_sv_undef);
-
-void
-flags(...)
- PPCODE:
- EXTEND(SP, 2);
- mPUSHu(RXapif_ONE);
- mPUSHu(RXapif_ALL);
diff --git a/t/op/magic.t b/t/op/magic.t
index 2a7a627d86..e0dfcf93a1 100644
--- a/t/op/magic.t
+++ b/t/op/magic.t
@@ -5,7 +5,7 @@ BEGIN {
chdir 't' if -d 't';
require './test.pl';
set_up_inc( '../lib' );
- plan (tests => 195); # some tests are run in BEGIN block
+ plan (tests => 192); # some tests are run in BEGIN block
}
# Test that defined() returns true for magic variables created on the fly,
@@ -483,8 +483,7 @@ SKIP: {
}
# Check that we don't auto-load packages
-foreach (['powie::!', 'Errno'],
- ['powie::+', 'Tie::Hash::NamedCapture']) {
+foreach (['powie::!', 'Errno']) {
my ($symbol, $package) = @$_;
SKIP: {
(my $extension = $package) =~ s|::|/|g;
@@ -613,10 +612,9 @@ SKIP: {
}
SKIP: {
- skip_if_miniperl("No XS in miniperl", 2);
+ skip_if_miniperl("No XS in miniperl", 1);
- for ( [qw( %- Tie::Hash::NamedCapture )],
- [qw( %! Errno )] ) {
+ for ( [qw( %! Errno )] ) {
my ($var, $mod) = @$_;
my $modfile = $mod =~ s|::|/|gr . ".pm";
fresh_perl_is
diff --git a/universal.c b/universal.c
index 34a63e894e..3658b9b8a1 100644
--- a/universal.c
+++ b/universal.c
@@ -1019,6 +1019,161 @@ XS(XS_Internals_getcwd)
#endif
+XS(XS_NamedCapture_tie_it)
+{
+ dXSARGS;
+
+ if (items != 1)
+ croak_xs_usage(cv, "sv");
+ {
+ SV *sv = ST(0);
+ GV * const gv = (GV *)sv;
+ HV * const hv = GvHVn(gv);
+ SV *rv = newSV_type(SVt_IV);
+ const char *gv_name = GvNAME(gv);
+
+ SvRV_set(rv, newSVuv(
+ strEQ(gv_name, "-") || strEQ(gv_name, "\003APTURE_ALL")
+ ? RXapif_ALL : RXapif_ONE));
+ SvROK_on(rv);
+ sv_bless(rv, GvSTASH(CvGV(cv)));
+
+ sv_unmagic((SV *)hv, PERL_MAGIC_tied);
+ sv_magic((SV *)hv, rv, PERL_MAGIC_tied, NULL, 0);
+ SvREFCNT_dec(rv); /* As sv_magic increased it by one. */
+ }
+ XSRETURN_EMPTY;
+}
+
+XS(XS_NamedCapture_TIEHASH)
+{
+ dVAR; dXSARGS;
+ if (items < 1)
+ croak_xs_usage(cv, "package, ...");
+ {
+ const char * package = (const char *)SvPV_nolen(ST(0));
+ UV flag = RXapif_ONE;
+ mark += 2;
+ while(mark < sp) {
+ STRLEN len;
+ const char *p = SvPV_const(*mark, len);
+ if(memEQs(p, len, "all"))
+ flag = SvTRUE(mark[1]) ? RXapif_ALL : RXapif_ONE;
+ mark += 2;
+ }
+ ST(0) = sv_2mortal(newSV_type(SVt_IV));
+ sv_setuv(newSVrv(ST(0), package), flag);
+ }
+ XSRETURN(1);
+}
+
+/* These are tightly coupled to the RXapif_* flags defined in regexp.h */
+#define UNDEF_FATAL 0x80000
+#define DISCARD 0x40000
+#define EXPECT_SHIFT 24
+#define ACTION_MASK 0x000FF
+
+#define FETCH_ALIAS (RXapif_FETCH | (2 << EXPECT_SHIFT))
+#define STORE_ALIAS (RXapif_STORE | (3 << EXPECT_SHIFT) | UNDEF_FATAL | DISCARD)
+#define DELETE_ALIAS (RXapif_DELETE | (2 << EXPECT_SHIFT) | UNDEF_FATAL)
+#define CLEAR_ALIAS (RXapif_CLEAR | (1 << EXPECT_SHIFT) | UNDEF_FATAL | DISCARD)
+#define EXISTS_ALIAS (RXapif_EXISTS | (2 << EXPECT_SHIFT))
+#define SCALAR_ALIAS (RXapif_SCALAR | (1 << EXPECT_SHIFT))
+
+XS(XS_NamedCapture_FETCH)
+{
+ dVAR; dXSARGS;
+ dXSI32;
+ PERL_UNUSED_VAR(cv); /* -W */
+ PERL_UNUSED_VAR(ax); /* -Wall */
+ SP -= items;
+ {
+ REGEXP *const rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
+ U32 flags;
+ SV *ret;
+ const U32 action = ix & ACTION_MASK;
+ const int expect = ix >> EXPECT_SHIFT;
+ if (items != expect)
+ croak_xs_usage(cv, expect == 2 ? "$key"
+ : (expect == 3 ? "$key, $value"
+ : ""));
+
+ if (!rx || !SvROK(ST(0))) {
+ if (ix & UNDEF_FATAL)
+ Perl_croak_no_modify();
+ else
+ XSRETURN_UNDEF;
+ }
+
+ flags = (U32)SvUV(SvRV(MUTABLE_SV(ST(0))));
+
+ PUTBACK;
+ ret = RX_ENGINE(rx)->named_buff(aTHX_ (rx), expect >= 2 ? ST(1) : NULL,
+ expect >= 3 ? ST(2) : NULL, flags | action);
+ SPAGAIN;
+
+ if (ix & DISCARD) {
+ /* Called with G_DISCARD, so our return stack state is thrown away.
+ Hence if we were returned anything, free it immediately. */
+ SvREFCNT_dec(ret);
+ } else {
+ PUSHs(ret ? sv_2mortal(ret) : &PL_sv_undef);
+ }
+ PUTBACK;
+ return;
+ }
+}
+
+
+XS(XS_NamedCapture_FIRSTKEY)
+{
+ dVAR; dXSARGS;
+ dXSI32;
+ PERL_UNUSED_VAR(cv); /* -W */
+ PERL_UNUSED_VAR(ax); /* -Wall */
+ SP -= items;
+ {
+ REGEXP *const rx = PL_curpm ? PM_GETRE(PL_curpm) : NULL;
+ U32 flags;
+ SV *ret;
+ const int expect = ix ? 2 : 1;
+ const U32 action = ix ? RXapif_NEXTKEY : RXapif_FIRSTKEY;
+ if (items != expect)
+ croak_xs_usage(cv, expect == 2 ? "$lastkey" : "");
+
+ if (!rx || !SvROK(ST(0)))
+ XSRETURN_UNDEF;
+
+ flags = (U32)SvUV(SvRV(MUTABLE_SV(ST(0))));
+
+ PUTBACK;
+ ret = RX_ENGINE(rx)->named_buff_iter(aTHX_ (rx),
+ expect >= 2 ? ST(1) : NULL,
+ flags | action);
+ SPAGAIN;
+
+ PUSHs(ret ? sv_2mortal(ret) : &PL_sv_undef);
+ PUTBACK;
+ return;
+ }
+}
+
+/* is this still needed? */
+XS(XS_NamedCapture_flags)
+{
+ dVAR; dXSARGS;
+ PERL_UNUSED_VAR(cv); /* -W */
+ PERL_UNUSED_VAR(ax); /* -Wall */
+ SP -= items;
+ {
+ EXTEND(SP, 2);
+ mPUSHu(RXapif_ONE);
+ mPUSHu(RXapif_ALL);
+ PUTBACK;
+ return;
+ }
+}
+
#include "vutil.h"
#include "vxs.inc"
@@ -1026,36 +1181,48 @@ struct xsub_details {
const char *name;
XSUBADDR_t xsub;
const char *proto;
+ int ix;
};
static const struct xsub_details these_details[] = {
- {"UNIVERSAL::isa", XS_UNIVERSAL_isa, NULL},
- {"UNIVERSAL::can", XS_UNIVERSAL_can, NULL},
- {"UNIVERSAL::DOES", XS_UNIVERSAL_DOES, NULL},
+ {"UNIVERSAL::isa", XS_UNIVERSAL_isa, NULL, 0 },
+ {"UNIVERSAL::can", XS_UNIVERSAL_can, NULL, 0 },
+ {"UNIVERSAL::DOES", XS_UNIVERSAL_DOES, NULL, 0 },
#define VXS_XSUB_DETAILS
#include "vxs.inc"
#undef VXS_XSUB_DETAILS
- {"utf8::is_utf8", XS_utf8_is_utf8, NULL},
- {"utf8::valid", XS_utf8_valid, NULL},
- {"utf8::encode", XS_utf8_encode, NULL},
- {"utf8::decode", XS_utf8_decode, NULL},
- {"utf8::upgrade", XS_utf8_upgrade, NULL},
- {"utf8::downgrade", XS_utf8_downgrade, NULL},
- {"utf8::native_to_unicode", XS_utf8_native_to_unicode, NULL},
- {"utf8::unicode_to_native", XS_utf8_unicode_to_native, NULL},
- {"Internals::SvREADONLY", XS_Internals_SvREADONLY, "\\[$%@];$"},
- {"Internals::SvREFCNT", XS_Internals_SvREFCNT, "\\[$%@];$"},
- {"Internals::hv_clear_placeholders", XS_Internals_hv_clear_placehold, "\\%"},
- {"constant::_make_const", XS_constant__make_const, "\\[$@]"},
- {"PerlIO::get_layers", XS_PerlIO_get_layers, "*;@"},
- {"re::is_regexp", XS_re_is_regexp, "$"},
- {"re::regname", XS_re_regname, ";$$"},
- {"re::regnames", XS_re_regnames, ";$"},
- {"re::regnames_count", XS_re_regnames_count, ""},
- {"re::regexp_pattern", XS_re_regexp_pattern, "$"},
+ {"utf8::is_utf8", XS_utf8_is_utf8, NULL, 0 },
+ {"utf8::valid", XS_utf8_valid, NULL, 0 },
+ {"utf8::encode", XS_utf8_encode, NULL, 0 },
+ {"utf8::decode", XS_utf8_decode, NULL, 0 },
+ {"utf8::upgrade", XS_utf8_upgrade, NULL, 0 },
+ {"utf8::downgrade", XS_utf8_downgrade, NULL, 0 },
+ {"utf8::native_to_unicode", XS_utf8_native_to_unicode, NULL, 0 },
+ {"utf8::unicode_to_native", XS_utf8_unicode_to_native, NULL, 0 },
+ {"Internals::SvREADONLY", XS_Internals_SvREADONLY, "\\[$%@];$", 0 },
+ {"Internals::SvREFCNT", XS_Internals_SvREFCNT, "\\[$%@];$", 0 },
+ {"Internals::hv_clear_placeholders", XS_Internals_hv_clear_placehold, "\\%", 0 },
+ {"constant::_make_const", XS_constant__make_const, "\\[$@]", 0 },
+ {"PerlIO::get_layers", XS_PerlIO_get_layers, "*;@", 0 },
+ {"re::is_regexp", XS_re_is_regexp, "$", 0 },
+ {"re::regname", XS_re_regname, ";$$", 0 },
+ {"re::regnames", XS_re_regnames, ";$", 0 },
+ {"re::regnames_count", XS_re_regnames_count, "", 0 },
+ {"re::regexp_pattern", XS_re_regexp_pattern, "$", 0 },
#ifdef HAS_GETCWD
- {"Internals::getcwd", XS_Internals_getcwd, ""},
+ {"Internals::getcwd", XS_Internals_getcwd, "", 0 },
#endif
+ {"Tie::Hash::NamedCapture::_tie_it", XS_NamedCapture_tie_it, NULL, 0 },
+ {"Tie::Hash::NamedCapture::TIEHASH", XS_NamedCapture_TIEHASH, NULL, 0 },
+ {"Tie::Hash::NamedCapture::FETCH", XS_NamedCapture_FETCH, NULL, FETCH_ALIAS },
+ {"Tie::Hash::NamedCapture::STORE", XS_NamedCapture_FETCH, NULL, STORE_ALIAS },
+ {"Tie::Hash::NamedCapture::DELETE", XS_NamedCapture_FETCH, NULL, DELETE_ALIAS },
+ {"Tie::Hash::NamedCapture::CLEAR", XS_NamedCapture_FETCH, NULL, CLEAR_ALIAS },
+ {"Tie::Hash::NamedCapture::EXISTS", XS_NamedCapture_FETCH, NULL, EXISTS_ALIAS },
+ {"Tie::Hash::NamedCapture::SCALAR", XS_NamedCapture_FETCH, NULL, SCALAR_ALIAS },
+ {"Tie::Hash::NamedCapture::FIRSTKEY", XS_NamedCapture_FIRSTKEY, NULL, 0 },
+ {"Tie::Hash::NamedCapture::NEXTKEY", XS_NamedCapture_FIRSTKEY, NULL, 1 },
+ {"Tie::Hash::NamedCapture::flags", XS_NamedCapture_flags, NULL, 0 },
};
STATIC OP*
@@ -1115,7 +1282,8 @@ Perl_boot_core_UNIVERSAL(pTHX)
const struct xsub_details *end = C_ARRAY_END(these_details);
do {
- newXS_flags(xsub->name, xsub->xsub, file, xsub->proto, 0);
+ CV *cv = newXS_flags(xsub->name, xsub->xsub, file, xsub->proto, 0);
+ XSANY.any_i32 = xsub->ix;
} while (++xsub < end);
#ifndef EBCDIC
diff --git a/vxs.inc b/vxs.inc
index b5c00d7de1..cea9857887 100644
--- a/vxs.inc
+++ b/vxs.inc
@@ -5,7 +5,7 @@
# define VXS_CLASS "version"
# define VXSp(name) XS_##name
/* VXSXSDP = XSUB Details Proto */
-# define VXSXSDP(x) x
+# define VXSXSDP(x) x, 0
#else
# define VXS_CLASS "version::vxs"
# define VXSp(name) VXS_##name