my $qr=qr/^normal$/; my $bqr=bless qr/^blessed$/,"Foo"; print "Normal : $qr\n"; print "Blessed: $bqr\n"; #### Normal : (?-xism:^normal$) Blessed: Foo=SCALAR(0x1acf020) #### SV * regexp(sv) SV * sv PROTOTYPE: $ PREINIT: STRLEN patlen; char *pattern; char reflags[6]; int left; PPCODE: { /* 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 undef. 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 blessed into the package Regexp and stringified normally. */ if (SvMAGICAL(sv)) { /* is this if needed??? Why?*/ mg_get(sv); } if(!SvROK(sv)) { /* bail if we dont have a ref. */ XSRETURN_UNDEF; } patlen=0; left=0; if (SvTHINKFIRST(sv)) { sv = (SV*)SvRV(sv); if (sv) { MAGIC *mg; if (SvTYPE(sv)==SVt_PVMG) { if ( ((SvFLAGS(sv) & (SVs_OBJECT|SVf_OK|SVs_GMG|SVs_SMG|SVs_RMG)) == (SVs_OBJECT|SVs_RMG)) && (mg = mg_find(sv, 'r'))) { /* Housten, we have a regex! */ regexp *re = (regexp *)mg->mg_obj; I32 gimme = GIMME_V; if ( gimme == G_ARRAY ) { /* we are in list/array context so stringify the modifiers that apply. We ignore "negative modifiers" in this scenario. Also we dont cache the modifiers. AFAICT there isnt anywhere for them to go. :-( */ char *fptr = "msix"; char ch; U16 reganch = (U16)((re->reganch & PMf_COMPILETIME) >> 12); while((ch = *fptr++)) { if(reganch & 1) { reflags[left++] = ch; } reganch >>= 1; } /* return the pattern and the modifiers */ XPUSHs(sv_2mortal(newSVpvn(re->precomp,re->prelen))); XPUSHs(sv_2mortal(newSVpvn(reflags,left))); XSRETURN(2); } else { /* Non array/list context. So we build up the stringified form just as PL_sv_2pv does, and like it we also cache the result. The entire content of the if() is directly taken from PL_sv_2pv */ if (!mg->mg_ptr ) { char *fptr = "msix"; char ch; int right = 4; U16 reganch = (U16)((re->reganch & PMf_COMPILETIME) >> 12); while((ch = *fptr++)) { if(reganch & 1) { reflags[left++] = ch; } else { reflags[right--] = ch; } reganch >>= 1; } if(left != 4) { reflags[left] = '-'; left = 5; } mg->mg_len = re->prelen + 4 + left; New(616, mg->mg_ptr, mg->mg_len + 1 + left, char); Copy("(?", mg->mg_ptr, 2, char); Copy(reflags, mg->mg_ptr+2, left, char); Copy(":", mg->mg_ptr+left+2, 1, char); Copy(re->precomp, mg->mg_ptr+3+left, re->prelen, char); mg->mg_ptr[mg->mg_len - 1] = ')'; mg->mg_ptr[mg->mg_len] = 0; } /* return the pattern in (?msix:..) format */ XPUSHs(sv_2mortal(newSVpvn(mg->mg_ptr, mg->mg_len))); XSRETURN(1); } } } } } /* 'twould appear it aint a regex, so return undef/empty list */ XSRETURN_UNDEF; } #### my $qr=qr/^foo$/; while (length $qr < 1000) { print "$qr\n"; $qr=eval "qr/$qr/" or die $@; } #### (?-xism:^foo$) (?-xism:(?-xism:^foo$)) (?-xism:(?-xism:(?-xism:^foo$))) (?-xism:(?-xism:(?-xism:(?-xism:^foo$)))) (?-xism:(?-xism:(?-xism:(?-xism:(?-xism:^foo$))))) (?-xism:(?-xism:(?-xism:(?-xism:(?-xism:(?-xism:^foo$)))))) ...