Commit | Line | Data |
79072805 |
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 | |