2 /********************************************
4 copyright 1991, Michael D. Brennan
6 This is a source file for mawk, an implementation of
7 the AWK programming language.
9 Mawk is distributed without warranty under the terms of
10 the GNU General Public License, version 2, 1991.
11 ********************************************/
14 * Revision 1.3 1993/07/24 17:55:12 mike
17 * Revision 1.2 1993/07/23 13:21:44 mike
20 * Revision 1.1.1.1 1993/07/03 18:58:28 mike
23 * Revision 3.8 1992/12/24 00:36:44 mike
24 * fixed major bozo for LMDOS when growing stack
25 * fixed potential LMDOS bozo with M_STR+U_ON+END_ON
26 * fixed minor bug in M_CLASS+U_ON+END_ON
28 * Revision 3.7 92/01/21 17:33:15 brennan
29 * added some casts so that character classes work with signed chars
31 * Revision 3.6 91/10/29 10:54:03 brennan
34 * Revision 3.5 91/08/13 09:10:15 brennan
37 * Revision 3.4 91/08/08 07:53:34 brennan
38 * work around for turboC realloc() bug
40 * Revision 3.4 91/08/07 07:10:47 brennan
41 * work around for TurboC realloc() bug
43 * Revision 3.3 91/08/04 15:45:57 brennan
44 * minor change for large model dos
46 * Revision 3.2 91/06/10 16:18:14 brennan
49 * Revision 3.1 91/06/07 10:33:25 brennan
52 * Revision 1.8 91/06/05 09:01:33 brennan
53 * changes to RE_new_run_stack
55 * Revision 1.7 91/05/31 10:56:02 brennan
56 * stack_empty hack for DOS large model
62 /* test a string against a machine */
66 #define STACKGROWTH 16
69 static RT_STATE *PROTO(slow_push, (RT_STATE *, STATE *, char *, int)) ;
73 RT_STATE *RE_run_stack_base ;
74 RT_STATE *RE_run_stack_limit ;
76 /* Large model DOS segment arithemetic breaks the current stack.
77 This hack fixes it without rewriting the whole thing, 5/31/91 */
78 RT_STATE *RE_run_stack_empty ;
83 if (!RE_run_stack_base)
85 RE_run_stack_base = (RT_STATE *)
86 RE_malloc(sizeof(RT_STATE) * STACKGROWTH) ;
87 RE_run_stack_limit = RE_run_stack_base + STACKGROWTH ;
88 RE_run_stack_empty = RE_run_stack_base - 1 ;
92 /* sometimes during REmatch(), this stack can grow pretty large.
93 In real life cases, the back tracking usually fails. Some
94 work is needed here to improve the algorithm.
95 I.e., figure out how not to stack useless paths.
101 int oldsize = RE_run_stack_limit - RE_run_stack_base ;
102 int newsize = oldsize + STACKGROWTH ;
104 #ifdef LMDOS /* large model DOS */
105 /* have to worry about overflow on multiplication (ugh) */
106 if (newsize >= 4096) RE_run_stack_base = (RT_STATE *) 0 ;
110 RE_run_stack_base = (RT_STATE *) realloc(RE_run_stack_base,
111 newsize * sizeof(RT_STATE)) ;
113 if (!RE_run_stack_base)
115 fprintf(stderr, "out of memory for RE run time stack\n") ;
116 /* this is pretty unusual, I've only seen it happen on
117 weird input to REmatch() under 16bit DOS , the same
118 situation worked easily on 32bit machine. */
122 RE_run_stack_limit = RE_run_stack_base + newsize ;
123 RE_run_stack_empty = RE_run_stack_base - 1 ;
125 /* return the new stackp */
126 return RE_run_stack_base + oldsize ;
131 slow_push(sp, m, s, u)
137 if (sp == RE_run_stack_limit) sp = RE_new_run_stack() ;
138 sp->m = m ; sp->s = s ; sp->u = u ;
144 #define push(mx,sx,ux) stackp = slow_push(++stackp, mx, sx, ux)
146 #define push(mx,sx,ux) if (++stackp == RE_run_stack_limit)\
147 stackp = RE_new_run_stack() ;\
148 stackp->m=(mx);stackp->s=(sx);stackp->u=(ux)
152 #define CASE_UANY(x) case x + U_OFF : case x + U_ON
154 /* test if str ~ /machine/
162 register STATE *m = (STATE *) machine ;
163 register char *s = str ;
164 register RT_STATE *stackp ;
167 int t ; /*convenient temps */
170 /* handle the easy case quickly */
171 if ((m + 1)->type == M_ACCEPT && m->type == M_STR)
172 return str_str(s, m->data.str, m->len) != (char *) 0 ;
175 u_flag = U_ON ; str_end = (char *) 0 ;
176 stackp = RE_run_stack_empty ;
181 if (stackp == RE_run_stack_empty) return 0 ;
184 u_flag = stackp--->u ;
189 switch (m->type + u_flag)
191 case M_STR + U_OFF + END_OFF:
192 if (strncmp(s, m->data.str, m->len)) goto refill ;
196 case M_STR + U_OFF + END_ON:
197 if (strcmp(s, m->data.str)) goto refill ;
201 case M_STR + U_ON + END_OFF:
202 if (!(s = str_str(s, m->data.str, m->len))) goto refill ;
203 push(m, s + 1, U_ON) ;
204 s += m->len ; m++ ; u_flag = U_OFF ;
207 case M_STR + U_ON + END_ON:
208 if (!str_end) str_end = s + strlen(s) ;
209 t = (str_end - s) - m->len ;
210 if (t < 0 || memcmp(s + t, m->data.str, m->len))
212 s = str_end ; m++ ; u_flag = U_OFF ;
215 case M_CLASS + U_OFF + END_OFF:
216 if (!ison(*m->data.bvp, s[0])) goto refill ;
220 case M_CLASS + U_OFF + END_ON:
221 if (s[1] || !ison(*m->data.bvp, s[0])) goto refill ;
225 case M_CLASS + U_ON + END_OFF:
226 while (!ison(*m->data.bvp, s[0]))
228 if (s[0] == 0) goto refill ;
233 m++ ; u_flag = U_OFF ;
236 case M_CLASS + U_ON + END_ON:
237 if (!str_end) str_end = s + strlen(s) ;
238 if (s[0] == 0 || !ison(*m->data.bvp, str_end[-1]))
240 s = str_end ; m++ ; u_flag = U_OFF ;
243 case M_ANY + U_OFF + END_OFF:
244 if (s[0] == 0) goto refill ;
248 case M_ANY + U_OFF + END_ON:
249 if (s[0] == 0 || s[1] != 0) goto refill ;
253 case M_ANY + U_ON + END_OFF:
254 if (s[0] == 0) goto refill ;
257 m++ ; u_flag = U_OFF ;
260 case M_ANY + U_ON + END_ON:
261 if (s[0] == 0) goto refill ;
262 if (!str_end) str_end = s + strlen(s) ;
263 s = str_end ; m++ ; u_flag = U_OFF ;
266 case M_START + U_OFF + END_OFF:
267 case M_START + U_ON + END_OFF:
268 if (s != str) goto refill ;
269 m++ ; u_flag = U_OFF ;
272 case M_START + U_OFF + END_ON:
273 case M_START + U_ON + END_ON:
274 if (s != str || s[0] != 0) goto refill ;
275 m++ ; u_flag = U_OFF ;
279 if (s[0] != 0) goto refill ;
280 m++ ; goto reswitch ;
284 m++ ; u_flag = U_OFF ;
288 u_flag = U_ON ; m++ ;
295 CASE_UANY(M_2JA): /* take the non jump branch */
296 /* don't stack an ACCEPT */
297 if ((tm = m + m->data.jump)->type == M_ACCEPT) return 1 ;
298 push(tm, s, u_flag) ;
302 CASE_UANY(M_2JB): /* take the jump branch */
303 /* don't stack an ACCEPT */
304 if ((tm = m + 1)->type == M_ACCEPT) return 1 ;
305 push(tm, s, u_flag) ;
313 RE_panic("unexpected case in REtest") ;
322 is_string_split(p, lenp)
326 if (p[0].type == M_STR && p[1].type == M_ACCEPT)
331 else return (char *) 0 ;
333 #else /* mawk provides its own str_str */
336 str_str(target, key, klen)
337 register char *target ;
349 return strchr(target, c) ;
355 while (target = strchr(target, c))
357 if (target[1] == c1) return target ;
365 while (target = strchr(target, c))
367 if (memcmp(target + 1, key, klen) == 0) return target ;