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