This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Regex Utility Functions and Substituion Fix (XML::Twig core dump)
[perl5.git] / ext / re / re.xs
CommitLineData
41b16711
AD
1#if defined(PERL_EXT_RE_DEBUG) && !defined(DEBUGGING)
2# define DEBUGGING
3#endif
4
c5be433b 5#define PERL_NO_GET_CONTEXT
56953603
IZ
6#include "EXTERN.h"
7#include "perl.h"
8#include "XSUB.h"
9
f9f4320a 10
97f88e98
JH
11START_EXTERN_C
12
cea2e8a9
GS
13extern regexp* my_regcomp (pTHX_ char* exp, char* xend, PMOP* pm);
14extern I32 my_regexec (pTHX_ regexp* prog, char* stringarg, char* strend,
20ce7b12
GS
15 char* strbeg, I32 minend, SV* screamer,
16 void* data, U32 flags);
f722798b
IZ
17extern void my_regfree (pTHX_ struct regexp* r);
18extern char* my_re_intuit_start (pTHX_ regexp *prog, SV *sv, char *strpos,
19 char *strend, U32 flags,
20 struct re_scream_pos_data_s *data);
21extern SV* my_re_intuit_string (pTHX_ regexp *prog);
de8c5301 22extern char* my_reg_stringify (pTHX_ MAGIC *mg, U32 *flags, STRLEN *lp, I32 *haseval);
56953603 23
a3c0e9ca 24#if defined(USE_ITHREADS)
f9f4320a 25extern regexp* my_regdupe (pTHX_ const regexp *r, CLONE_PARAMS *param);
a3c0e9ca 26#endif
0a28d81c 27
9b47c5f6 28EXTERN_C const struct regexp_engine my_reg_engine = {
f9f4320a
YO
29 my_regcomp,
30 my_regexec,
31 my_re_intuit_start,
32 my_re_intuit_string,
33 my_regfree,
de8c5301 34 my_reg_stringify,
a3c0e9ca 35#if defined(USE_ITHREADS)
f9f4320a 36 my_regdupe
a3c0e9ca 37#endif
0a28d81c
NC
38};
39
f9f4320a 40END_EXTERN_C
56953603
IZ
41
42MODULE = re PACKAGE = re
43
44void
f9f4320a
YO
45install()
46 PPCODE:
47 PL_colorset = 0; /* Allow reinspection of ENV. */
48 /* PL_debug |= DEBUG_r_FLAG; */
49 XPUSHs(sv_2mortal(newSViv(PTR2IV(&my_reg_engine))));
50
de8c5301
YO
51
52void
53is_regexp(sv)
54 SV * sv
55PROTOTYPE: $
56PREINIT:
57 MAGIC *mg;
58PPCODE:
59{
60 if (SvMAGICAL(sv))
61 mg_get(sv);
62 if (SvROK(sv) &&
63 (sv = (SV*)SvRV(sv)) && /* assign deliberate */
64 SvTYPE(sv) == SVt_PVMG &&
65 (mg = mg_find(sv, PERL_MAGIC_qr))) /* assign deliberate */
66 {
67 XSRETURN_YES;
68 } else {
69 XSRETURN_NO;
70 }
71 /* NOTREACHED */
72}
73
74void
75regexp_pattern(sv)
76 SV * sv
77PROTOTYPE: $
78PREINIT:
79 MAGIC *mg;
80PPCODE:
81{
82 /*
83 Checks if a reference is a regex or not. If the parameter is
84 not a ref, or is not the result of a qr// then returns false
85 in scalar context and an empty list in list context.
86 Otherwise in list context it returns the pattern and the
87 modifiers, in scalar context it returns the pattern just as it
88 would if the qr// was stringified normally, regardless as
89 to the class of the variable and any strigification overloads
90 on the object.
91 */
92
93 if (SvMAGICAL(sv))
94 mg_get(sv);
95 if (SvROK(sv) &&
96 (sv = (SV*)SvRV(sv)) && /* assign deliberate */
97 SvTYPE(sv) == SVt_PVMG &&
98 (mg = mg_find(sv, PERL_MAGIC_qr))) /* assign deliberate */
99 {
100
101 /* Housten, we have a regex! */
102 SV *pattern;
103 regexp *re = (regexp *)mg->mg_obj;
104 STRLEN patlen = 0;
105 STRLEN left = 0;
106 char reflags[6];
107
108 if ( GIMME_V == G_ARRAY ) {
109 /*
110 we are in list context so stringify
111 the modifiers that apply. We ignore "negative
112 modifiers" in this scenario.
113 */
114
115 char *fptr = "msix";
116 char ch;
117 U16 reganch = (U16)((re->reganch & PMf_COMPILETIME) >> 12);
118
119 while((ch = *fptr++)) {
120 if(reganch & 1) {
121 reflags[left++] = ch;
122 }
123 reganch >>= 1;
124 }
125
126 pattern = sv_2mortal(newSVpvn(re->precomp,re->prelen));
127 if (re->reganch & ROPT_UTF8) SvUTF8_on(pattern);
128
129 /* return the pattern and the modifiers */
130 XPUSHs(pattern);
131 XPUSHs(sv_2mortal(newSVpvn(reflags,left)));
132 XSRETURN(2);
133 } else {
134 /* Scalar, so use the string that Perl would return */
135 if (!mg->mg_ptr)
136 CALLREG_STRINGIFY(mg,0,0);
137
138 /* return the pattern in (?msix:..) format */
139 pattern = sv_2mortal(newSVpvn(mg->mg_ptr,mg->mg_len));
140 if (re->reganch & ROPT_UTF8)
141 SvUTF8_on(pattern);
142 XPUSHs(pattern);
143 XSRETURN(1);
144 }
145 } else {
146 /* It ain't a regexp folks */
147 if ( GIMME_V == G_ARRAY ) {
148 /* return the empty list */
149 XSRETURN_UNDEF;
150 } else {
151 /* Because of the (?:..) wrapping involved in a
152 stringified pattern it is impossible to get a
153 result for a real regexp that would evaluate to
154 false. Therefore we can return PL_sv_no to signify
155 that the object is not a regex, this means that one
156 can say
157
158 if (regex($might_be_a_regex) eq '(?:foo)') { }
159
160 and not worry about undefined values.
161 */
162 XSRETURN_NO;
163 }
164 }
165 /* NOT-REACHED */
166}