perl 5.0 alpha 3
[perl.git] / do / match
1 int
2 do_match(TARG,arg,gimme,arglast)
3 STR *TARG;
4 register ARG *arg;
5 int gimme;
6 int *arglast;
7 {
8     register STR **st = stack->ary_array;
9     register SPAT *spat = arg[2].arg_ptr.arg_spat;
10     register char *t;
11     register int sp = arglast[0] + 1;
12     STR *srchstr = st[sp];
13     register char *s = str_get(st[sp]);
14     char *strend = s + st[sp]->str_cur;
15     STR *tmpstr;
16     char *myhint = hint;
17     int global;
18     int safebase;
19     char *truebase = s;
20     register REGEXP *rx = spat->spat_regexp;
21
22     hint = Nullch;
23     if (!spat) {
24         if (gimme == G_ARRAY)
25             return --sp;
26         str_set(TARG,Yes);
27         STABSET(TARG);
28         st[sp] = TARG;
29         return sp;
30     }
31     global = spat->spat_flags & SPAT_GLOBAL;
32     safebase = (gimme == G_ARRAY) || global;
33     if (!s)
34         fatal("panic: do_match");
35     if (spat->spat_flags & SPAT_USED) {
36 #ifdef DEBUGGING
37         if (debug & 8)
38             deb("2.SPAT USED\n");
39 #endif
40         if (gimme == G_ARRAY)
41             return --sp;
42         str_set(TARG,No);
43         STABSET(TARG);
44         st[sp] = TARG;
45         return sp;
46     }
47     --sp;
48     if (spat->spat_runtime) {
49         nointrp = "|)";
50         sp = eval(spat->spat_runtime,G_SCALAR,sp);
51         st = stack->ary_array;
52         t = str_get(tmpstr = st[sp--]);
53         nointrp = "";
54 #ifdef DEBUGGING
55         if (debug & 8)
56             deb("2.SPAT /%s/\n",t);
57 #endif
58         if (!global && rx)
59             regfree(rx);
60         spat->spat_regexp = Null(REGEXP*);      /* crucial if regcomp aborts */
61         spat->spat_regexp = regcomp(t,t+tmpstr->str_cur,
62             spat->spat_flags & SPAT_FOLD);
63         if (!spat->spat_regexp->prelen && lastspat)
64             spat = lastspat;
65         if (spat->spat_flags & SPAT_KEEP) {
66             if (!(spat->spat_flags & SPAT_FOLD))
67                 scanconst(spat,spat->spat_regexp->precomp,
68                     spat->spat_regexp->prelen);
69             if (spat->spat_runtime)
70                 arg_free(spat->spat_runtime);   /* it won't change, so */
71             spat->spat_runtime = Nullarg;       /* no point compiling again */
72             hoistmust(spat);
73             if (curcmd->c_expr && (curcmd->c_flags & CF_OPTIMIZE) == CFT_EVAL) {
74                 curcmd->c_flags &= ~CF_OPTIMIZE;
75                 opt_arg(curcmd, 1, curcmd->c_type == C_EXPR);
76             }
77         }
78         if (global) {
79             if (rx) {
80                 if (rx->startp[0]) {
81                     s = rx->endp[0];
82                     if (s == rx->startp[0])
83                         s++;
84                     if (s > strend) {
85                         regfree(rx);
86                         rx = spat->spat_regexp;
87                         goto nope;
88                     }
89                 }
90                 regfree(rx);
91             }
92         }
93         else if (!spat->spat_regexp->nparens)
94             gimme = G_SCALAR;                   /* accidental array context? */
95         rx = spat->spat_regexp;
96         if (regexec(rx, s, strend, s, 0,
97           srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr,
98           safebase)) {
99             if (rx->subbase || global)
100                 curspat = spat;
101             lastspat = spat;
102             goto gotcha;
103         }
104         else {
105             if (gimme == G_ARRAY)
106                 return sp;
107             str_sset(TARG,&str_no);
108             STABSET(TARG);
109             st[++sp] = TARG;
110             return sp;
111         }
112     }
113     else {
114 #ifdef DEBUGGING
115         if (debug & 8) {
116             char ch;
117
118             if (spat->spat_flags & SPAT_ONCE)
119                 ch = '?';
120             else
121                 ch = '/';
122             deb("2.SPAT %c%s%c\n",ch,rx->precomp,ch);
123         }
124 #endif
125         if (!rx->prelen && lastspat) {
126             spat = lastspat;
127             rx = spat->spat_regexp;
128         }
129         t = s;
130     play_it_again:
131         if (global && rx->startp[0]) {
132             t = s = rx->endp[0];
133             if (s == rx->startp[0])
134                 s++,t++;
135             if (s > strend)
136                 goto nope;
137         }
138         if (myhint) {
139             if (myhint < s || myhint > strend)
140                 fatal("panic: hint in do_match");
141             s = myhint;
142             if (rx->regback >= 0) {
143                 s -= rx->regback;
144                 if (s < t)
145                     s = t;
146             }
147             else
148                 s = t;
149         }
150         else if (spat->spat_short) {
151             if (spat->spat_flags & SPAT_SCANFIRST) {
152                 if (srchstr->str_pok & SP_STUDIED) {
153                     if (screamfirst[spat->spat_short->str_rare] < 0)
154                         goto nope;
155                     else if (!(s = screaminstr(srchstr,spat->spat_short)))
156                         goto nope;
157                     else if (spat->spat_flags & SPAT_ALL)
158                         goto yup;
159                 }
160 #ifndef lint
161                 else if (!(s = fbminstr((unsigned char*)s,
162                   (unsigned char*)strend, spat->spat_short)))
163                     goto nope;
164 #endif
165                 else if (spat->spat_flags & SPAT_ALL)
166                     goto yup;
167                 if (s && rx->regback >= 0) {
168                     ++spat->spat_short->str_u.str_useful;
169                     s -= rx->regback;
170                     if (s < t)
171                         s = t;
172                 }
173                 else
174                     s = t;
175             }
176             else if (!multiline && (*spat->spat_short->str_ptr != *s ||
177               bcmp(spat->spat_short->str_ptr, s, spat->spat_slen) ))
178                 goto nope;
179             if (--spat->spat_short->str_u.str_useful < 0) {
180                 str_free(spat->spat_short);
181                 spat->spat_short = Nullstr;     /* opt is being useless */
182             }
183         }
184         if (!rx->nparens && !global) {
185             gimme = G_SCALAR;                   /* accidental array context? */
186             safebase = FALSE;
187         }
188         if (regexec(rx, s, strend, truebase, 0,
189           srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr,
190           safebase)) {
191             if (rx->subbase || global)
192                 curspat = spat;
193             lastspat = spat;
194             if (spat->spat_flags & SPAT_ONCE)
195                 spat->spat_flags |= SPAT_USED;
196             goto gotcha;
197         }
198         else {
199             if (global)
200                 rx->startp[0] = Nullch;
201             if (gimme == G_ARRAY)
202                 return sp;
203             str_sset(TARG,&str_no);
204             STABSET(TARG);
205             st[++sp] = TARG;
206             return sp;
207         }
208     }
209     /*NOTREACHED*/
210
211   gotcha:
212     if (gimme == G_ARRAY) {
213         int iters, i, len;
214
215         iters = rx->nparens;
216         if (global && !iters)
217             i = 1;
218         else
219             i = 0;
220         if (sp + iters + i >= stack->ary_max) {
221             astore(stack,sp + iters + i, Nullstr);
222             st = stack->ary_array;              /* possibly realloced */
223         }
224
225         for (i = !i; i <= iters; i++) {
226             st[++sp] = str_mortal(&str_no);
227             /*SUPPRESS 560*/
228             if (s = rx->startp[i]) {
229                 len = rx->endp[i] - s;
230                 if (len > 0)
231                     str_nset(st[sp],s,len);
232             }
233         }
234         if (global) {
235             truebase = rx->subbeg;
236             goto play_it_again;
237         }
238         return sp;
239     }
240     else {
241         str_sset(TARG,&str_yes);
242         STABSET(TARG);
243         st[++sp] = TARG;
244         return sp;
245     }
246
247 yup:
248     ++spat->spat_short->str_u.str_useful;
249     lastspat = spat;
250     if (spat->spat_flags & SPAT_ONCE)
251         spat->spat_flags |= SPAT_USED;
252     if (global) {
253         rx->subbeg = t;
254         rx->subend = strend;
255         rx->startp[0] = s;
256         rx->endp[0] = s + spat->spat_short->str_cur;
257         curspat = spat;
258         goto gotcha;
259     }
260     if (sawampersand) {
261         char *tmps;
262
263         if (rx->subbase)
264             Safefree(rx->subbase);
265         tmps = rx->subbase = nsavestr(t,strend-t);
266         rx->subbeg = tmps;
267         rx->subend = tmps + (strend-t);
268         tmps = rx->startp[0] = tmps + (s - t);
269         rx->endp[0] = tmps + spat->spat_short->str_cur;
270         curspat = spat;
271     }
272     str_sset(TARG,&str_yes);
273     STABSET(TARG);
274     st[++sp] = TARG;
275     return sp;
276
277 nope:
278     rx->startp[0] = Nullch;
279     if (spat->spat_short)
280         ++spat->spat_short->str_u.str_useful;
281     if (gimme == G_ARRAY)
282         return sp;
283     str_sset(TARG,&str_no);
284     STABSET(TARG);
285     st[++sp] = TARG;
286     return sp;
287 }
288