]> git.vpit.fr Git - perl/modules/re-engine-Plugin.git/blob - Plugin.xs
Importing re-engine-Plugin-0.04_01.tar.gz
[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 Plugin_comp(pTHX_ const SV * const pattern, const U32 flags)
43 {
44     dSP;
45     REGEXP * rx;
46     re__engine__Plugin re;
47     I32 count;
48     I32 buffers;
49
50     /* exp/xend version of the pattern & length */
51     STRLEN plen;
52     char*  exp = SvPV((SV*)pattern, plen);
53     char* xend = exp + plen;
54
55     /* The REGEXP structure to return to perl */
56     Newxz(rx, 1, REGEXP);
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     re->rx = rx;                   /* Make the rx accessible from self->rx */
65     rx->refcnt = 1;                /* Refcount so we won' be destroyed */
66     rx->intflags = flags;          /* Flags for internal use */
67     rx->extflags = flags;          /* Flags for perl to use */
68     rx->engine = RE_ENGINE_PLUGIN; /* Compile to use this engine */
69
70     /* Precompiled regexp for pp_regcomp to use */
71     rx->prelen = plen;
72     rx->precomp = savepvn(exp, rx->prelen);
73
74     /* Set up qr// stringification to be equivalent to the supplied
75      * pattern, this should be done via overload eventually.
76      */
77     rx->wraplen = rx->prelen;
78     Newx(rx->wrapped, rx->wraplen, char);
79     Copy(rx->precomp, rx->wrapped, rx->wraplen, char);
80
81     /* Store our private object */
82     rx->pprivate = obj;
83
84     /* Store the pattern for ->pattern */
85     re->pattern = (SV*)pattern;
86     SvREFCNT_inc(re->pattern);
87
88     /*
89      * Call our callback function if one was defined, if not we've
90      * already set up all the stuff we're going to to need for
91      * subsequent exec and other calls
92      */
93     SV * callback = get_H_callback("comp");
94
95     if (callback) {
96         ENTER;    
97         SAVETMPS;
98    
99         PUSHMARK(SP);
100         XPUSHs(obj);
101         PUTBACK;
102
103         call_sv(callback, G_DISCARD);
104
105         FREETMPS;
106         LEAVE;
107     }
108
109     /* If any of the comp-time accessors were called we'll have to
110      * update the regexp struct with the new info.
111      */
112
113     buffers = rx->nparens;
114
115     Newxz(rx->offs, buffers, regexp_paren_pair);
116
117     return rx;
118 }
119
120 I32
121 Plugin_exec(pTHX_ REGEXP * const rx, char *stringarg, char *strend,
122             char *strbeg, I32 minend, SV *sv, void *data, U32 flags)
123 {
124     dSP;
125     I32 matched;
126     SV * callback = get_H_callback("exec");
127     GET_SELF_FROM_PPRIVATE(rx->pprivate);
128
129     if (callback) {
130         /* Store the current str for ->str */
131         self->str = (SV*)sv;
132         SvREFCNT_inc(self->str);
133
134         ENTER;
135         SAVETMPS;
136    
137         PUSHMARK(SP);
138         XPUSHs(rx->pprivate);
139         XPUSHs(sv);
140         PUTBACK;
141
142         call_sv(callback, G_SCALAR);
143  
144         SPAGAIN;
145
146         SV * ret = POPs;
147
148         if (SvTRUE(ret))
149             matched = 1;
150         else
151             matched = 0;
152
153         PUTBACK;
154         FREETMPS;
155         LEAVE;
156     } else {
157         matched = 0;
158     }
159
160     return matched;
161 }
162
163 char *
164 Plugin_intuit(pTHX_ REGEXP * const rx, SV *sv, char *strpos,
165                      char *strend, U32 flags, re_scream_pos_data *data)
166 {
167     PERL_UNUSED_ARG(rx);
168     PERL_UNUSED_ARG(sv);
169     PERL_UNUSED_ARG(strpos);
170     PERL_UNUSED_ARG(strend);
171     PERL_UNUSED_ARG(flags);
172     PERL_UNUSED_ARG(data);
173     return NULL;
174 }
175
176 SV *
177 Plugin_checkstr(pTHX_ REGEXP * const rx)
178 {
179     PERL_UNUSED_ARG(rx);
180     return NULL;
181 }
182
183 void
184 Plugin_free(pTHX_ REGEXP * const rx)
185 {
186     PERL_UNUSED_ARG(rx);
187 /*
188     dSP;
189     SV * callback;
190     GET_SELF_FROM_PPRIVATE(rx->pprivate);
191
192     callback = self->cb_free;
193
194     if (callback) {
195         ENTER;
196         SAVETMPS;
197    
198         PUSHMARK(SP);
199         XPUSHs(rx->pprivate);
200         PUTBACK;
201
202         call_sv(callback, G_DISCARD);
203
204         PUTBACK;
205         FREETMPS;
206         LEAVE;
207     }
208     return;
209 */
210 }
211
212 void *
213 Plugin_dupe(pTHX_ const REGEXP * rx, CLONE_PARAMS *param)
214 {
215     Perl_croak("dupe not supported yet");
216     return rx->pprivate;
217 }
218
219 void
220 Plugin_numbered_buff_FETCH(pTHX_ REGEXP * const rx, const I32 paren,
221                            SV * const sv)
222 {
223     dSP;
224     I32 items;
225     SV * callback;
226     GET_SELF_FROM_PPRIVATE(rx->pprivate);
227
228     callback = self->cb_num_capture_buff_FETCH;
229
230     if (callback) {
231         ENTER;
232         SAVETMPS;
233    
234         PUSHMARK(SP);
235         XPUSHs(rx->pprivate);
236         XPUSHs(sv_2mortal(newSViv(paren)));
237         PUTBACK;
238
239         items = call_sv(callback, G_SCALAR);
240         
241         if (items == 1) {
242             SPAGAIN;
243
244             SV * ret = POPs;
245             sv_setsv(sv, ret);
246         } else {
247             sv_setsv(sv, &PL_sv_undef);
248         }
249
250         PUTBACK;
251         FREETMPS;
252         LEAVE;
253     } else {
254         sv_setsv(sv, &PL_sv_undef);
255     }
256 }
257
258 void
259 Plugin_numbered_buff_STORE(pTHX_ REGEXP * const rx, const I32 paren,
260                            SV const * const value)
261 {
262     dSP;
263     I32 items;
264     SV * callback;
265     GET_SELF_FROM_PPRIVATE(rx->pprivate);
266
267     callback = self->cb_num_capture_buff_STORE;
268
269     if (callback) {
270         ENTER;
271         SAVETMPS;
272    
273         PUSHMARK(SP);
274         XPUSHs(rx->pprivate);
275         XPUSHs(sv_2mortal(newSViv(paren)));
276         XPUSHs(SvREFCNT_inc(value));
277         PUTBACK;
278
279         call_sv(callback, G_DISCARD);
280
281         PUTBACK;
282         FREETMPS;
283         LEAVE;
284     }
285 }
286
287 I32
288 Plugin_numbered_buff_LENGTH(pTHX_ REGEXP * const rx, const SV * const sv,
289                               const I32 paren)
290 {
291     dSP;
292     I32 items;
293     SV * callback;
294     GET_SELF_FROM_PPRIVATE(rx->pprivate);
295
296     callback = self->cb_num_capture_buff_LENGTH;
297
298     if (callback) {
299         ENTER;
300         SAVETMPS;
301    
302         PUSHMARK(SP);
303         XPUSHs(rx->pprivate);
304         XPUSHs(sv_2mortal(newSViv(paren)));
305         PUTBACK;
306
307         call_sv(callback, G_SCALAR);
308
309         SPAGAIN;
310
311         IV ret = POPi;
312
313         PUTBACK;
314         FREETMPS;
315         LEAVE;
316
317         return (I32)ret;
318     } else {
319         /* TODO: call FETCH and get the length on that value */
320         return 0;
321     }
322 }
323
324
325 SV*
326 Plugin_named_buff_FETCH(pTHX_ REGEXP * const rx, SV * const key, U32 flags)
327 {
328     dSP;
329     SV * callback;
330     GET_SELF_FROM_PPRIVATE(rx->pprivate);
331
332     callback = self->cb_named_capture_buff_FETCH;
333
334     if (callback) {
335         ENTER;
336         SAVETMPS;
337    
338         PUSHMARK(SP);
339         XPUSHs(rx->pprivate);
340         XPUSHs(SvREFCNT_inc(key));
341         XPUSHs(sv_2mortal(newSViv(flags & 1 ? 1 : 0)));
342         PUTBACK;
343
344         call_sv(callback, G_SCALAR);
345
346         SPAGAIN;
347
348         SV* ret = POPs;
349         SvREFCNT_inc(ret);
350
351         PUTBACK;
352         FREETMPS;
353         LEAVE;
354
355         return ret;
356     } else {
357         return NULL;
358     }
359 }
360
361 void
362 Plugin_named_buff_STORE(pTHX_ REGEXP * const rx, SV * const key,
363                         SV * const value, const U32 flags)
364 {
365     dSP;
366     SV * callback;
367     GET_SELF_FROM_PPRIVATE(rx->pprivate);
368
369     callback = self->cb_named_capture_buff_STORE;
370
371     if (callback) {
372         ENTER;
373         SAVETMPS;
374    
375         PUSHMARK(SP);
376         XPUSHs(rx->pprivate);
377         XPUSHs(SvREFCNT_inc(key));
378         XPUSHs(SvREFCNT_inc(value));
379         XPUSHs(sv_2mortal(newSViv(flags)));
380         PUTBACK;
381
382         call_sv(callback, G_DISCARD);
383
384         PUTBACK;
385         FREETMPS;
386         LEAVE;
387     }
388 }
389
390 void
391 Plugin_named_buff_DELETE(pTHX_ REGEXP * const rx, SV * const key, const U32 flags)
392 {
393     dSP;
394     SV * callback;
395     GET_SELF_FROM_PPRIVATE(rx->pprivate);
396
397     callback = self->cb_named_capture_buff_DELETE;
398
399     if (callback) {
400         ENTER;
401         SAVETMPS;
402    
403         PUSHMARK(SP);
404         XPUSHs(rx->pprivate);
405         XPUSHs(SvREFCNT_inc(key));
406         XPUSHs(sv_2mortal(newSViv(flags)));
407         PUTBACK;
408
409         call_sv(callback, G_DISCARD);
410
411         PUTBACK;
412         FREETMPS;
413         LEAVE;
414     }
415 }
416
417 void
418 Plugin_named_buff_CLEAR(pTHX_ REGEXP * const rx, const U32 flags)
419 {
420     dSP;
421     SV * callback;
422     GET_SELF_FROM_PPRIVATE(rx->pprivate);
423
424     callback = self->cb_named_capture_buff_CLEAR;
425
426     if (callback) {
427         ENTER;
428         SAVETMPS;
429    
430         PUSHMARK(SP);
431         XPUSHs(rx->pprivate);
432         XPUSHs(sv_2mortal(newSViv(flags)));
433         PUTBACK;
434
435         call_sv(callback, G_DISCARD);
436
437         PUTBACK;
438         FREETMPS;
439         LEAVE;
440     }
441 }
442
443 bool
444 Plugin_named_buff_EXISTS(pTHX_ REGEXP * const rx, SV * const key,
445                          const U32 flags)
446 {
447     dSP;
448     SV * callback;
449     bool truthiness = FALSE;
450     GET_SELF_FROM_PPRIVATE(rx->pprivate);
451
452     callback = self->cb_named_capture_buff_EXISTS;
453
454     if (callback) {
455         ENTER;
456         SAVETMPS;
457    
458         PUSHMARK(SP);
459         XPUSHs(rx->pprivate);
460         XPUSHs(SvREFCNT_inc(key));
461         XPUSHs(sv_2mortal(newSViv(flags)));
462         PUTBACK;
463
464         call_sv(callback, G_SCALAR);
465
466         SPAGAIN;
467
468         SV * ret = POPs;
469         truthiness = SvTRUE(ret);
470
471         PUTBACK;
472         FREETMPS;
473         LEAVE;
474     }
475
476     return truthiness;
477 }
478
479 SV*
480 Plugin_named_buff_FIRSTKEY(pTHX_ REGEXP * const rx, const U32 flags)
481 {
482     dSP;
483     SV * callback;
484     GET_SELF_FROM_PPRIVATE(rx->pprivate);
485
486     callback = self->cb_named_capture_buff_FIRSTKEY;
487
488     if (callback) {
489         ENTER;
490         SAVETMPS;
491    
492         PUSHMARK(SP);
493         XPUSHs(rx->pprivate);
494         XPUSHs(sv_2mortal(newSViv(flags)));
495         PUTBACK;
496
497         call_sv(callback, G_SCALAR);
498
499         SPAGAIN;
500
501         SV * ret = POPs;
502         SvREFCNT_inc(ret);
503
504         PUTBACK;
505         FREETMPS;
506         LEAVE;
507
508         return ret;
509     } else {
510         return NULL;
511     }
512 }
513
514 SV*
515 Plugin_named_buff_NEXTKEY(pTHX_ REGEXP * const rx, SV * const lastkey,
516                           const U32 flags)
517 {
518     dSP;
519     SV * callback;
520     GET_SELF_FROM_PPRIVATE(rx->pprivate);
521
522     callback = self->cb_named_capture_buff_NEXTKEY;
523
524     if (callback) {
525         ENTER;
526         SAVETMPS;
527    
528         PUSHMARK(SP);
529         XPUSHs(rx->pprivate);
530         XPUSHs(SvREFCNT_inc(lastkey));
531         XPUSHs(sv_2mortal(newSViv(flags)));
532         PUTBACK;
533
534         call_sv(callback, G_SCALAR);
535
536         SPAGAIN;
537
538         SV * ret = POPs;
539         SvREFCNT_inc(ret);
540
541         PUTBACK;
542         FREETMPS;
543         LEAVE;
544
545         return ret;
546     } else {
547         return NULL;
548     }
549 }
550
551 SV*
552 Plugin_named_buff_SCALAR(pTHX_ REGEXP * const rx, const U32 flags)
553 {
554     dSP;
555     SV * callback;
556     GET_SELF_FROM_PPRIVATE(rx->pprivate);
557
558     callback = self->cb_named_capture_buff_SCALAR;
559
560     if (callback) {
561         ENTER;
562         SAVETMPS;
563    
564         PUSHMARK(SP);
565         XPUSHs(rx->pprivate);
566         XPUSHs(sv_2mortal(newSViv(flags)));
567         PUTBACK;
568
569         call_sv(callback, G_SCALAR);
570
571         SPAGAIN;
572
573         SV * ret = POPs;
574         SvREFCNT_inc(ret);
575
576         PUTBACK;
577         FREETMPS;
578         LEAVE;
579
580         return ret;
581     } else {
582         return NULL;
583     }
584 }
585
586 SV*
587 Plugin_package(pTHX_ REGEXP * const rx)
588 {
589     PERL_UNUSED_ARG(rx);
590     return newSVpvs("re::engine::Plugin");
591 }
592
593 MODULE = re::engine::Plugin     PACKAGE = re::engine::Plugin
594 PROTOTYPES: DISABLE
595
596 void
597 pattern(re::engine::Plugin self, ...)
598 PPCODE:
599     XPUSHs(self->pattern);
600
601 void
602 str(re::engine::Plugin self, ...)
603 PPCODE:
604     XPUSHs(self->str);
605
606 void
607 mod(re::engine::Plugin self, ...)
608 PPCODE:
609     /* /i */
610     if (self->rx->intflags & PMf_FOLD) {
611       XPUSHs(sv_2mortal(newSVpvs("i")));
612       XPUSHs(&PL_sv_yes);
613     }
614
615     /* /m */
616     if (self->rx->intflags & PMf_MULTILINE) {
617       XPUSHs(sv_2mortal(newSVpvs("m")));
618       XPUSHs(&PL_sv_yes);
619     }
620
621     /* /s */
622     if (self->rx->intflags & PMf_SINGLELINE) {
623       XPUSHs(sv_2mortal(newSVpvs("s")));
624       XPUSHs(&PL_sv_yes);
625     }
626
627     /* /x */
628     if (self->rx->intflags & PMf_EXTENDED) {
629       XPUSHs(sv_2mortal(newSVpvs("x")));
630       XPUSHs(&PL_sv_yes);
631     }
632
633     /* /p */
634     if (self->rx->intflags & RXf_PMf_KEEPCOPY) {
635       XPUSHs(sv_2mortal(newSVpvs("p")));
636       XPUSHs(&PL_sv_yes);
637     }
638
639 void
640 stash(re::engine::Plugin self, ...)
641 PPCODE:
642     if (items > 1) {
643         self->stash = ST(1);
644         SvREFCNT_inc(self->stash);
645         XSRETURN_EMPTY;
646     } else {
647         XPUSHs(self->stash);
648     }
649
650 void
651 minlen(re::engine::Plugin self, ...)
652 PPCODE:
653     if (items > 1) {
654         self->rx->minlen = (I32)SvIV(ST(1));
655         XSRETURN_EMPTY;
656     } else {
657         if (self->rx->minlen) {
658             XPUSHs(sv_2mortal(newSViv(self->rx->minlen)));
659         } else {
660             XPUSHs(sv_2mortal(&PL_sv_undef));
661         }
662     }
663
664 void
665 gofs(re::engine::Plugin self, ...)
666 PPCODE:
667     if (items > 1) {
668         self->rx->gofs = (U32)SvIV(ST(1));
669         XSRETURN_EMPTY;
670     } else {
671         if (self->rx->gofs) {
672             XPUSHs(sv_2mortal(newSVuv(self->rx->gofs)));
673         } else {
674             XPUSHs(sv_2mortal(&PL_sv_undef));
675         }
676     }
677
678 void
679 nparens(re::engine::Plugin self, ...)
680 PPCODE:
681     if (items > 1) {
682         self->rx->nparens = (U32)SvIV(ST(1));
683         XSRETURN_EMPTY;
684     } else {
685         if (self->rx->nparens) {
686             XPUSHs(sv_2mortal(newSVuv(self->rx->nparens)));
687         } else {
688             XPUSHs(sv_2mortal(&PL_sv_undef));
689         }
690     }
691
692 void
693 _num_capture_buff_FETCH(re::engine::Plugin self, ...)
694 PPCODE:
695     if (items > 1) {
696         self->cb_num_capture_buff_FETCH = ST(1);
697         SvREFCNT_inc(self->cb_num_capture_buff_FETCH);
698     }
699
700 void
701 _num_capture_buff_STORE(re::engine::Plugin self, ...)
702 PPCODE:
703     if (items > 1) {
704         self->cb_num_capture_buff_STORE = ST(1);
705         SvREFCNT_inc(self->cb_num_capture_buff_STORE);
706     }
707
708 void
709 _num_capture_buff_LENGTH(re::engine::Plugin self, ...)
710 PPCODE:
711     if (items > 1) {
712         self->cb_num_capture_buff_LENGTH = ST(1);
713         SvREFCNT_inc(self->cb_num_capture_buff_LENGTH);
714     }
715
716 void
717 _named_capture_buff_FETCH(re::engine::Plugin self, ...)
718 PPCODE:
719     if (items > 1) {
720         self->cb_named_capture_buff_FETCH = ST(1);
721         SvREFCNT_inc(self->cb_named_capture_buff_FETCH);
722     }
723
724 void
725 _named_capture_buff_STORE(re::engine::Plugin self, ...)
726 PPCODE:
727     if (items > 1) {
728         self->cb_named_capture_buff_STORE = ST(1);
729         SvREFCNT_inc(self->cb_named_capture_buff_STORE);
730     }
731
732 void
733 _named_capture_buff_DELETE(re::engine::Plugin self, ...)
734 PPCODE:
735     if (items > 1) {
736         self->cb_named_capture_buff_DELETE = ST(1);
737         SvREFCNT_inc(self->cb_named_capture_buff_DELETE);
738     }
739
740 void
741 _named_capture_buff_CLEAR(re::engine::Plugin self, ...)
742 PPCODE:
743     if (items > 1) {
744         self->cb_named_capture_buff_CLEAR = ST(1);
745         SvREFCNT_inc(self->cb_named_capture_buff_CLEAR);
746     }
747
748 void
749 _named_capture_buff_EXISTS(re::engine::Plugin self, ...)
750 PPCODE:
751     if (items > 1) {
752         self->cb_named_capture_buff_EXISTS = ST(1);
753         SvREFCNT_inc(self->cb_named_capture_buff_EXISTS);
754     }
755
756 void
757 _named_capture_buff_FIRSTKEY(re::engine::Plugin self, ...)
758 PPCODE:
759     if (items > 1) {
760         self->cb_named_capture_buff_FIRSTKEY = ST(1);
761         SvREFCNT_inc(self->cb_named_capture_buff_FIRSTKEY);
762     }
763
764 void
765 _named_capture_buff_NEXTKEY(re::engine::Plugin self, ...)
766 PPCODE:
767     if (items > 1) {
768         self->cb_named_capture_buff_NEXTKEY = ST(1);
769         SvREFCNT_inc(self->cb_named_capture_buff_NEXTKEY);
770     }
771
772 void
773 _named_capture_buff_SCALAR(re::engine::Plugin self, ...)
774 PPCODE:
775     if (items > 1) {
776         self->cb_named_capture_buff_SCALAR = ST(1);
777         SvREFCNT_inc(self->cb_named_capture_buff_SCALAR);
778     }
779
780 void
781 ENGINE()
782 PPCODE:
783     XPUSHs(sv_2mortal(newSViv(PTR2IV(&engine_plugin))));