]> git.vpit.fr Git - perl/modules/re-engine-Plugin.git/blob - Plugin.xs
544fab8aa070cfc79b1d00ae2f6d33a84116f2eb
[perl/modules/re-engine-Plugin.git] / Plugin.xs
1 #include "EXTERN.h"
2 #include "perl.h"
3 #include "XSUB.h"
4 #include "Plugin.h"
5
6 SV*
7 get_H_callback(const char* key)
8 {
9     dVAR;
10     dSP;
11
12     SV * callback;
13
14     ENTER;
15     SAVETMPS;
16    
17     PUSHMARK(SP);
18     XPUSHs(sv_2mortal(newSVpv(key, 0)));
19     PUTBACK;
20
21     call_pv("re::engine::Plugin::_get_callback", G_SCALAR);
22
23     SPAGAIN;
24
25     callback = POPs;
26     SvREFCNT_inc(callback); /* refcount++ or FREETMPS below will collect us */
27
28     /* If we don't get a valid CODE value return a NULL callback, in
29      * that case the hooks won't call back into Perl space */
30     if (!SvROK(callback) || SvTYPE(SvRV(callback)) != SVt_PVCV) {
31         callback = NULL;
32     }
33
34     PUTBACK;
35     FREETMPS;
36     LEAVE;
37
38     return callback;
39 }
40
41 REGEXP *
42 #if PERL_VERSION <= 10
43 Plugin_comp(pTHX_ const SV * const pattern, const U32 flags)
44 #else
45 Plugin_comp(pTHX_ SV * const pattern, U32 flags)
46 #endif
47 {
48     dSP;
49     struct regexp * rx;
50     REGEXP *RX;
51     re__engine__Plugin re;
52     I32 buffers;
53
54     /* exp/xend version of the pattern & length */
55     STRLEN plen;
56     char*  exp = SvPV((SV*)pattern, plen);
57
58     /* Our blessed object */
59     SV *obj = newSV(0);
60     SvREFCNT_inc(obj);
61     Newxz(re, 1, struct replug);
62     sv_setref_pv(obj, "re::engine::Plugin", (void*)re);
63
64     newREGEXP(RX);
65     rx = rxREGEXP(RX);
66
67     re->rx = rx;                   /* Make the rx accessible from self->rx */
68     rx->intflags = flags;          /* Flags for internal use */
69     rx->extflags = flags;          /* Flags for perl to use */
70     rx->engine = RE_ENGINE_PLUGIN; /* Compile to use this engine */
71
72 #if PERL_VERSION <= 10
73     rx->refcnt = 1;                /* Refcount so we won't be destroyed */
74
75     /* Precompiled pattern for pp_regcomp to use */
76     rx->prelen = plen;
77     rx->precomp = savepvn(exp, rx->prelen);
78
79     /* Set up qr// stringification to be equivalent to the supplied
80      * pattern, this should be done via overload eventually.
81      */
82     rx->wraplen = rx->prelen;
83     Newx(rx->wrapped, rx->wraplen, char);
84     Copy(rx->precomp, rx->wrapped, rx->wraplen, char);
85 #endif
86
87     /* Store our private object */
88     rx->pprivate = obj;
89
90     /* Store the pattern for ->pattern */
91     re->pattern = (SV*)pattern;
92     SvREFCNT_inc(re->pattern);
93
94     /*
95      * Call our callback function if one was defined, if not we've
96      * already set up all the stuff we're going to to need for
97      * subsequent exec and other calls
98      */
99     SV * callback = get_H_callback("comp");
100
101     if (callback) {
102         ENTER;    
103         SAVETMPS;
104    
105         PUSHMARK(SP);
106         XPUSHs(obj);
107         PUTBACK;
108
109         call_sv(callback, G_DISCARD);
110
111         FREETMPS;
112         LEAVE;
113     }
114
115     /* If any of the comp-time accessors were called we'll have to
116      * update the regexp struct with the new info.
117      */
118
119     buffers = rx->nparens;
120
121     Newxz(rx->offs, buffers + 1, regexp_paren_pair);
122
123     return RX;
124 }
125
126 I32
127 Plugin_exec(pTHX_ REGEXP * const RX, char *stringarg, char *strend,
128             char *strbeg, I32 minend, SV *sv, void *data, U32 flags)
129 {
130     dSP;
131     I32 matched;
132     SV * callback = get_H_callback("exec");
133     struct regexp *rx = rxREGEXP(RX);
134     GET_SELF_FROM_PPRIVATE(rx->pprivate);
135
136     if (callback) {
137         /* Store the current str for ->str */
138         self->str = (SV*)sv;
139         SvREFCNT_inc(self->str);
140
141         ENTER;
142         SAVETMPS;
143    
144         PUSHMARK(SP);
145         XPUSHs(rx->pprivate);
146         XPUSHs(sv);
147         PUTBACK;
148
149         call_sv(callback, G_SCALAR);
150  
151         SPAGAIN;
152
153         SV * ret = POPs;
154
155         if (SvTRUE(ret))
156             matched = 1;
157         else
158             matched = 0;
159
160         PUTBACK;
161         FREETMPS;
162         LEAVE;
163     } else {
164         matched = 0;
165     }
166
167     return matched;
168 }
169
170 char *
171 Plugin_intuit(pTHX_ REGEXP * const RX, SV *sv, char *strpos,
172                      char *strend, U32 flags, re_scream_pos_data *data)
173 {
174     PERL_UNUSED_ARG(RX);
175     PERL_UNUSED_ARG(sv);
176     PERL_UNUSED_ARG(strpos);
177     PERL_UNUSED_ARG(strend);
178     PERL_UNUSED_ARG(flags);
179     PERL_UNUSED_ARG(data);
180     return NULL;
181 }
182
183 SV *
184 Plugin_checkstr(pTHX_ REGEXP * const RX)
185 {
186     PERL_UNUSED_ARG(RX);
187     return NULL;
188 }
189
190 void
191 Plugin_free(pTHX_ REGEXP * const RX)
192 {
193     PERL_UNUSED_ARG(RX);
194 /*
195     dSP;
196     SV * callback;
197     GET_SELF_FROM_PPRIVATE(rx->pprivate);
198
199     callback = self->cb_free;
200
201     if (callback) {
202         ENTER;
203         SAVETMPS;
204    
205         PUSHMARK(SP);
206         XPUSHs(rx->pprivate);
207         PUTBACK;
208
209         call_sv(callback, G_DISCARD);
210
211         PUTBACK;
212         FREETMPS;
213         LEAVE;
214     }
215     return;
216 */
217 }
218
219 void *
220 Plugin_dupe(pTHX_ REGEXP * const RX, CLONE_PARAMS *param)
221 {
222     struct regexp *rx = rxREGEXP(RX);
223     Perl_croak(aTHX_ "dupe not supported yet");
224     return rx->pprivate;
225 }
226
227
228 void
229 Plugin_numbered_buff_FETCH(pTHX_ REGEXP * const RX, const I32 paren,
230                            SV * const sv)
231 {
232     dSP;
233     I32 items;
234     SV * callback;
235     struct regexp *rx = rxREGEXP(RX);
236     GET_SELF_FROM_PPRIVATE(rx->pprivate);
237
238     callback = self->cb_num_capture_buff_FETCH;
239
240     if (callback) {
241         ENTER;
242         SAVETMPS;
243    
244         PUSHMARK(SP);
245         XPUSHs(rx->pprivate);
246         XPUSHs(sv_2mortal(newSViv(paren)));
247         PUTBACK;
248
249         items = call_sv(callback, G_SCALAR);
250         
251         if (items == 1) {
252             SPAGAIN;
253
254             SV * ret = POPs;
255             sv_setsv(sv, ret);
256         } else {
257             sv_setsv(sv, &PL_sv_undef);
258         }
259
260         PUTBACK;
261         FREETMPS;
262         LEAVE;
263     } else {
264         sv_setsv(sv, &PL_sv_undef);
265     }
266 }
267
268 void
269 Plugin_numbered_buff_STORE(pTHX_ REGEXP * const RX, const I32 paren,
270                            SV const * const value)
271 {
272     dSP;
273     SV * callback;
274     struct regexp *rx = rxREGEXP(RX);
275     GET_SELF_FROM_PPRIVATE(rx->pprivate);
276
277     callback = self->cb_num_capture_buff_STORE;
278
279     if (callback) {
280         ENTER;
281         SAVETMPS;
282    
283         PUSHMARK(SP);
284         XPUSHs(rx->pprivate);
285         XPUSHs(sv_2mortal(newSViv(paren)));
286         XPUSHs(SvREFCNT_inc((SV *) value));
287         PUTBACK;
288
289         call_sv(callback, G_DISCARD);
290
291         PUTBACK;
292         FREETMPS;
293         LEAVE;
294     }
295 }
296
297 I32
298 Plugin_numbered_buff_LENGTH(pTHX_ REGEXP * const RX, const SV * const sv,
299                               const I32 paren)
300 {
301     dSP;
302     SV * callback;
303     struct regexp *rx = rxREGEXP(RX);
304     GET_SELF_FROM_PPRIVATE(rx->pprivate);
305
306     callback = self->cb_num_capture_buff_LENGTH;
307
308     if (callback) {
309         ENTER;
310         SAVETMPS;
311    
312         PUSHMARK(SP);
313         XPUSHs(rx->pprivate);
314         XPUSHs(sv_2mortal(newSViv(paren)));
315         PUTBACK;
316
317         call_sv(callback, G_SCALAR);
318
319         SPAGAIN;
320
321         IV ret = POPi;
322
323         PUTBACK;
324         FREETMPS;
325         LEAVE;
326
327         return (I32)ret;
328     } else {
329         /* TODO: call FETCH and get the length on that value */
330         return 0;
331     }
332 }
333
334
335 SV*
336 Plugin_named_buff (pTHX_ REGEXP * const RX, SV * const key, SV * const value,
337                    const U32 flags)
338 {
339     return NULL;
340 }
341
342 SV*
343 Plugin_named_buff_iter (pTHX_ REGEXP * const RX, const SV * const lastkey,
344                         const U32 flags)
345 {
346     return NULL;
347 }
348
349 SV*
350 Plugin_package(pTHX_ REGEXP * const RX)
351 {
352     PERL_UNUSED_ARG(RX);
353     return newSVpvs("re::engine::Plugin");
354 }
355
356 MODULE = re::engine::Plugin     PACKAGE = re::engine::Plugin
357 PROTOTYPES: DISABLE
358
359 void
360 pattern(re::engine::Plugin self, ...)
361 PPCODE:
362     XPUSHs(self->pattern);
363
364 void
365 str(re::engine::Plugin self, ...)
366 PPCODE:
367     XPUSHs(self->str);
368
369 char*
370 mod(re::engine::Plugin self, ...)
371 PPCODE:
372     /* /i */
373     if (self->rx->intflags & PMf_FOLD) {
374       XPUSHs(sv_2mortal(newSVpvs("i")));
375       XPUSHs(&PL_sv_yes);
376     }
377
378     /* /m */
379     if (self->rx->intflags & PMf_MULTILINE) {
380       XPUSHs(sv_2mortal(newSVpvs("m")));
381       XPUSHs(&PL_sv_yes);
382     }
383
384     /* /s */
385     if (self->rx->intflags & PMf_SINGLELINE) {
386       XPUSHs(sv_2mortal(newSVpvs("s")));
387       XPUSHs(&PL_sv_yes);
388     }
389
390     /* /x */
391     if (self->rx->intflags & PMf_EXTENDED) {
392       XPUSHs(sv_2mortal(newSVpvs("x")));
393       XPUSHs(&PL_sv_yes);
394     }
395
396     /* /p */
397     if (self->rx->intflags & RXf_PMf_KEEPCOPY) {
398       XPUSHs(sv_2mortal(newSVpvs("p")));
399       XPUSHs(&PL_sv_yes);
400     }
401
402 void
403 stash(re::engine::Plugin self, ...)
404 PPCODE:
405     if (items > 1) {
406         self->stash = ST(1);
407         SvREFCNT_inc(self->stash);
408         XSRETURN_EMPTY;
409     } else {
410         XPUSHs(self->stash);
411     }
412
413 void
414 minlen(re::engine::Plugin self, ...)
415 PPCODE:
416     if (items > 1) {
417         self->rx->minlen = (I32)SvIV(ST(1));
418         XSRETURN_EMPTY;
419     } else {
420         if (self->rx->minlen) {
421             XPUSHs(sv_2mortal(newSViv(self->rx->minlen)));
422         } else {
423             XPUSHs(sv_2mortal(&PL_sv_undef));
424         }
425     }
426
427 void
428 gofs(re::engine::Plugin self, ...)
429 PPCODE:
430     if (items > 1) {
431         self->rx->gofs = (U32)SvIV(ST(1));
432         XSRETURN_EMPTY;
433     } else {
434         if (self->rx->gofs) {
435             XPUSHs(sv_2mortal(newSVuv(self->rx->gofs)));
436         } else {
437             XPUSHs(sv_2mortal(&PL_sv_undef));
438         }
439     }
440
441 void
442 nparens(re::engine::Plugin self, ...)
443 PPCODE:
444     if (items > 1) {
445         self->rx->nparens = (U32)SvIV(ST(1));
446         XSRETURN_EMPTY;
447     } else {
448         if (self->rx->nparens) {
449             XPUSHs(sv_2mortal(newSVuv(self->rx->nparens)));
450         } else {
451             XPUSHs(sv_2mortal(&PL_sv_undef));
452         }
453     }
454
455 void
456 _num_capture_buff_FETCH(re::engine::Plugin self, ...)
457 PPCODE:
458     if (items > 1) {
459         self->cb_num_capture_buff_FETCH = ST(1);
460         SvREFCNT_inc(self->cb_num_capture_buff_FETCH);
461     }
462
463 void
464 _num_capture_buff_STORE(re::engine::Plugin self, ...)
465 PPCODE:
466     if (items > 1) {
467         self->cb_num_capture_buff_STORE = ST(1);
468         SvREFCNT_inc(self->cb_num_capture_buff_STORE);
469     }
470
471 void
472 _num_capture_buff_LENGTH(re::engine::Plugin self, ...)
473 PPCODE:
474     if (items > 1) {
475         self->cb_num_capture_buff_LENGTH = ST(1);
476         SvREFCNT_inc(self->cb_num_capture_buff_LENGTH);
477     }
478
479 void
480 ENGINE()
481 PPCODE:
482     XPUSHs(sv_2mortal(newSViv(PTR2IV(&engine_plugin))));