Re: [PATCH] Cleanup of the regexp API
[p5sagit/p5-mst-13.2.git] / ext / re / re.xs
CommitLineData
41b16711 1#if defined(PERL_EXT_RE_DEBUG) && !defined(DEBUGGING)
2# define DEBUGGING
3#endif
4
c5be433b 5#define PERL_NO_GET_CONTEXT
56953603 6#include "EXTERN.h"
7#include "perl.h"
8#include "XSUB.h"
256ddcd0 9#include "re_comp.h"
56953603 10
f9f4320a 11
97f88e98 12START_EXTERN_C
13
49d7dfbc 14extern REGEXP* my_re_compile (pTHX_ const SV * const pattern, U32 pm_flags);
15extern I32 my_regexec (pTHX_ REGEXP * const prog, char* stringarg, char* strend,
20ce7b12 16 char* strbeg, I32 minend, SV* screamer,
17 void* data, U32 flags);
f8149455 18
49d7dfbc 19extern char* my_re_intuit_start (pTHX_ REGEXP * const prog, SV *sv, char *strpos,
f722798b 20 char *strend, U32 flags,
21 struct re_scream_pos_data_s *data);
49d7dfbc 22extern SV* my_re_intuit_string (pTHX_ REGEXP * const prog);
23
24extern void my_regfree (pTHX_ REGEXP * const r);
25extern void my_reg_numbered_buff_get(pTHX_ REGEXP * const rx, const I32 paren,
26 SV * const usesv);
27extern SV* my_reg_named_buff_get(pTHX_ REGEXP * const rx, SV * const namesv,
28 const U32 flags);
29extern SV* my_reg_qr_package(pTHX_ REGEXP * const rx);
a3c0e9ca 30#if defined(USE_ITHREADS)
49d7dfbc 31extern void* my_regdupe (pTHX_ REGEXP * const r, CLONE_PARAMS *param);
a3c0e9ca 32#endif
0a28d81c 33
70685ca0 34EXTERN_C const struct regexp_engine my_reg_engine;
35
36END_EXTERN_C
37
38const struct regexp_engine my_reg_engine = {
6d5c990f 39 my_re_compile,
f9f4320a 40 my_regexec,
41 my_re_intuit_start,
42 my_re_intuit_string,
43 my_regfree,
93b32b6d 44 my_reg_numbered_buff_get,
45 my_reg_named_buff_get,
49d7dfbc 46 my_reg_qr_package,
a3c0e9ca 47#if defined(USE_ITHREADS)
f9f4320a 48 my_regdupe
a3c0e9ca 49#endif
0a28d81c 50};
51
49d7dfbc 52REGEXP *
44a2ac75 53get_re_arg( pTHX_ SV *sv, U32 flags, MAGIC **mgp) {
54 MAGIC *mg;
55 if (sv) {
56 if (SvMAGICAL(sv))
57 mg_get(sv);
58 if (SvROK(sv) &&
59 (sv = (SV*)SvRV(sv)) && /* assign deliberate */
60 SvTYPE(sv) == SVt_PVMG &&
61 (mg = mg_find(sv, PERL_MAGIC_qr))) /* assign deliberate */
62 {
63 if (mgp) *mgp = mg;
49d7dfbc 64 return (REGEXP *)mg->mg_obj;
44a2ac75 65 }
66 }
67 if (mgp) *mgp = NULL;
68 return ((flags && PL_curpm) ? PM_GETRE(PL_curpm) : NULL);
69}
70
56953603 71MODULE = re PACKAGE = re
72
73void
f9f4320a 74install()
75 PPCODE:
76 PL_colorset = 0; /* Allow reinspection of ENV. */
77 /* PL_debug |= DEBUG_r_FLAG; */
78 XPUSHs(sv_2mortal(newSViv(PTR2IV(&my_reg_engine))));
79
de8c5301 80
81void
de8c5301 82regexp_pattern(sv)
83 SV * sv
84PROTOTYPE: $
85PREINIT:
86 MAGIC *mg;
49d7dfbc 87 REGEXP *re;
de8c5301 88PPCODE:
89{
90 /*
91 Checks if a reference is a regex or not. If the parameter is
92 not a ref, or is not the result of a qr// then returns false
93 in scalar context and an empty list in list context.
94 Otherwise in list context it returns the pattern and the
95 modifiers, in scalar context it returns the pattern just as it
96 would if the qr// was stringified normally, regardless as
97 to the class of the variable and any strigification overloads
98 on the object.
99 */
100
44a2ac75 101 if ( re = get_re_arg( aTHX_ sv, 0, &mg) ) /* assign deliberate */
de8c5301 102 {
de8c5301 103 /* Housten, we have a regex! */
104 SV *pattern;
de8c5301 105 STRLEN patlen = 0;
106 STRLEN left = 0;
107 char reflags[6];
108
109 if ( GIMME_V == G_ARRAY ) {
110 /*
111 we are in list context so stringify
112 the modifiers that apply. We ignore "negative
113 modifiers" in this scenario.
114 */
115
bcdf7404 116 char *fptr = INT_PAT_MODS;
de8c5301 117 char ch;
bbe252da 118 U16 match_flags = (U16)((re->extflags & PMf_COMPILETIME) >> 12);
de8c5301 119
120 while((ch = *fptr++)) {
bbe252da 121 if(match_flags & 1) {
de8c5301 122 reflags[left++] = ch;
123 }
bbe252da 124 match_flags >>= 1;
de8c5301 125 }
126
127 pattern = sv_2mortal(newSVpvn(re->precomp,re->prelen));
bbe252da 128 if (re->extflags & RXf_UTF8) SvUTF8_on(pattern);
de8c5301 129
130 /* return the pattern and the modifiers */
131 XPUSHs(pattern);
132 XPUSHs(sv_2mortal(newSVpvn(reflags,left)));
133 XSRETURN(2);
134 } else {
135 /* Scalar, so use the string that Perl would return */
de8c5301 136 /* return the pattern in (?msix:..) format */
bcdf7404 137 pattern = sv_2mortal(newSVpvn(re->wrapped,re->wraplen));
bbe252da 138 if (re->extflags & RXf_UTF8)
de8c5301 139 SvUTF8_on(pattern);
140 XPUSHs(pattern);
141 XSRETURN(1);
142 }
143 } else {
144 /* It ain't a regexp folks */
145 if ( GIMME_V == G_ARRAY ) {
146 /* return the empty list */
147 XSRETURN_UNDEF;
148 } else {
149 /* Because of the (?:..) wrapping involved in a
150 stringified pattern it is impossible to get a
151 result for a real regexp that would evaluate to
152 false. Therefore we can return PL_sv_no to signify
153 that the object is not a regex, this means that one
154 can say
155
156 if (regex($might_be_a_regex) eq '(?:foo)') { }
157
158 and not worry about undefined values.
159 */
160 XSRETURN_NO;
161 }
162 }
163 /* NOT-REACHED */
256ddcd0 164}
165
166
167void
168regmust(sv)
169 SV * sv
170PROTOTYPE: $
171PREINIT:
49d7dfbc 172 REGEXP *re;
256ddcd0 173PPCODE:
174{
44a2ac75 175 if ( re = get_re_arg( aTHX_ sv, 0, 0) ) /* assign deliberate */
256ddcd0 176 {
177 SV *an = &PL_sv_no;
178 SV *fl = &PL_sv_no;
256ddcd0 179 if (re->anchored_substr) {
180 an = newSVsv(re->anchored_substr);
181 } else if (re->anchored_utf8) {
182 an = newSVsv(re->anchored_utf8);
183 }
184 if (re->float_substr) {
185 fl = newSVsv(re->float_substr);
186 } else if (re->float_utf8) {
187 fl = newSVsv(re->float_utf8);
188 }
189 XPUSHs(an);
190 XPUSHs(fl);
191 XSRETURN(2);
192 }
193 XSRETURN_UNDEF;
194}
44a2ac75 195