diff options
author | Jerry D. Hedden <jdhedden@cpan.org> | 2008-01-08 10:01:02 -0500 |
---|---|---|
committer | Rafael Garcia-Suarez <rgarciasuarez@gmail.com> | 2008-01-09 10:54:27 +0000 |
commit | 192c1e277b50bfcbfdd3717ce2ae7c1a42fa9601 (patch) | |
tree | 3f970a6b8a3990c88ffdf00716b975ddc426dcee /universal.c | |
parent | 2e8342de65fb9cb7fd716c30bbddc9c0f4311ba0 (diff) | |
download | perl-192c1e277b50bfcbfdd3717ce2ae7c1a42fa9601.tar.gz |
Move re::regexp_pattern to universal.c
From: "Jerry D. Hedden" <jdhedden@cpan.org>
Message-ID: <1ff86f510801081201q5c36f055re6165ebfe8876c2e@mail.gmail.com>
p4raw-id: //depot/perl@32911
Diffstat (limited to 'universal.c')
-rw-r--r-- | universal.c | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/universal.c b/universal.c index a6b3f6e89e..c835286ab0 100644 --- a/universal.c +++ b/universal.c @@ -214,6 +214,7 @@ XS(XS_re_is_regexp); XS(XS_re_regname); XS(XS_re_regnames); XS(XS_re_regnames_count); +XS(XS_re_regexp_pattern); XS(XS_Tie_Hash_NamedCapture_FETCH); XS(XS_Tie_Hash_NamedCapture_STORE); XS(XS_Tie_Hash_NamedCapture_DELETE); @@ -277,6 +278,7 @@ Perl_boot_core_UNIVERSAL(pTHX) newXSproto("re::regname", XS_re_regname, file, ";$$"); newXSproto("re::regnames", XS_re_regnames, file, ";$"); newXSproto("re::regnames_count", XS_re_regnames_count, file, ""); + newXSproto("re::regexp_pattern", XS_re_regexp_pattern, file, "$"); newXS("Tie::Hash::NamedCapture::FETCH", XS_Tie_Hash_NamedCapture_FETCH, file); newXS("Tie::Hash::NamedCapture::STORE", XS_Tie_Hash_NamedCapture_STORE, file); newXS("Tie::Hash::NamedCapture::DELETE", XS_Tie_Hash_NamedCapture_DELETE, file); @@ -1187,6 +1189,99 @@ XS(XS_re_regnames) return; } +XS(XS_re_regexp_pattern) +{ + dVAR; + dXSARGS; + REGEXP *re; + PERL_UNUSED_ARG(cv); + + if (items != 1) + Perl_croak(aTHX_ "Usage: %s(%s)", "re::regexp_pattern", "sv"); + + SP -= items; + + /* + Checks if a reference is a regex or not. If the parameter is + not a ref, or is not the result of a qr// then returns false + in scalar context and an empty list in list context. + Otherwise in list context it returns the pattern and the + modifiers, in scalar context it returns the pattern just as it + would if the qr// was stringified normally, regardless as + to the class of the variable and any strigification overloads + on the object. + */ + + if ((re = SvRX(ST(0)))) /* assign deliberate */ + { + /* Housten, we have a regex! */ + SV *pattern; + STRLEN left = 0; + char reflags[6]; + + if ( GIMME_V == G_ARRAY ) { + /* + we are in list context so stringify + the modifiers that apply. We ignore "negative + modifiers" in this scenario. + */ + + const char *fptr = INT_PAT_MODS; + char ch; + U16 match_flags = (U16)((RX_EXTFLAGS(re) & PMf_COMPILETIME) + >> RXf_PMf_STD_PMMOD_SHIFT); + + while((ch = *fptr++)) { + if(match_flags & 1) { + reflags[left++] = ch; + } + match_flags >>= 1; + } + + pattern = sv_2mortal(newSVpvn(RX_PRECOMP(re),RX_PRELEN(re))); + if (RX_UTF8(re)) + SvUTF8_on(pattern); + + /* return the pattern and the modifiers */ + XPUSHs(pattern); + XPUSHs(sv_2mortal(newSVpvn(reflags,left))); + XSRETURN(2); + } else { + /* Scalar, so use the string that Perl would return */ + /* return the pattern in (?msix:..) format */ +#if PERL_VERSION >= 11 + pattern = sv_2mortal(newSVsv((SV*)re)); +#else + pattern = sv_2mortal(newSVpvn(RX_WRAPPED(re),RX_WRAPLEN(re))); + if (RX_UTF8(re)) + SvUTF8_on(pattern); +#endif + XPUSHs(pattern); + XSRETURN(1); + } + } else { + /* It ain't a regexp folks */ + if ( GIMME_V == G_ARRAY ) { + /* return the empty list */ + XSRETURN_UNDEF; + } else { + /* Because of the (?:..) wrapping involved in a + stringified pattern it is impossible to get a + result for a real regexp that would evaluate to + false. Therefore we can return PL_sv_no to signify + that the object is not a regex, this means that one + can say + + if (regex($might_be_a_regex) eq '(?:foo)') { } + + and not worry about undefined values. + */ + XSRETURN_NO; + } + } + /* NOT-REACHED */ +} + XS(XS_Tie_Hash_NamedCapture_FETCH) { dVAR; |