1/***********************************************************************
2*                                                                      *
3*               This software is part of the ast package               *
4*          Copyright (c) 1985-2012 AT&T Intellectual Property          *
5*                      and is licensed under the                       *
6*                 Eclipse Public License, Version 1.0                  *
7*                    by AT&T Intellectual Property                     *
8*                                                                      *
9*                A copy of the License is available at                 *
10*          http://www.eclipse.org/org/documents/epl-v10.html           *
11*         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12*                                                                      *
13*              Information and Software Systems Research               *
14*                            AT&T Research                             *
15*                           Florham Park NJ                            *
16*                                                                      *
17*                 Glenn Fowler <gsf@research.att.com>                  *
18*                  David Korn <dgk@research.att.com>                   *
19*                   Phong Vo <kpv@research.att.com>                    *
20*                                                                      *
21***********************************************************************/
22#pragma prototyped
23
24/*
25 * posix regex record executor
26 * multiple record sized-buffer interface
27 */
28
29#include "reglib.h"
30
31/*
32 * call regnexec() on records selected by Boyer-Moore
33 */
34
35int
36regrexec(const regex_t* p, const char* s, size_t len, size_t nmatch, regmatch_t* match, regflags_t flags, int sep, void* handle, regrecord_t record)
37{
38	register unsigned char*	buf = (unsigned char*)s;
39	register unsigned char*	beg;
40	register unsigned char*	l;
41	register unsigned char*	r;
42	register unsigned char*	x;
43	register size_t*	skip;
44	register size_t*	fail;
45	register Bm_mask_t**	mask;
46	register size_t		index;
47	register ssize_t	n;
48	unsigned char*		end;
49	size_t			mid;
50	int			complete;
51	int			exactlen;
52	int			leftlen;
53	int			rightlen;
54	int			inv;
55	Bm_mask_t		m;
56	Env_t*			env;
57	Rex_t*			e;
58
59	if (!s || !p || !(env = p->env) || (e = env->rex)->type != REX_BM)
60		return REG_BADPAT;
61	inv = (flags & REG_INVERT) != 0;
62	buf = beg = (unsigned char*)s;
63	end = buf + len;
64	mid = (len < e->re.bm.right) ? 0 : (len - e->re.bm.right);
65	skip = e->re.bm.skip;
66	fail = e->re.bm.fail;
67	mask = e->re.bm.mask;
68	complete = e->re.bm.complete && !nmatch;
69	exactlen = e->re.bm.size;
70	leftlen = e->re.bm.left + exactlen;
71	rightlen = exactlen + e->re.bm.right;
72	index = leftlen++;
73	for (;;)
74	{
75		while ((index += skip[buf[index]]) < mid);
76		if (index < HIT)
77			goto impossible;
78		index -= HIT;
79		m = mask[n = exactlen - 1][buf[index]];
80		do
81		{
82			if (!n--)
83				goto possible;
84		} while (m &= mask[n][buf[--index]]);
85		if ((index += fail[n + 1]) < len)
86			continue;
87 impossible:
88		if (inv)
89		{
90			l = r = buf + len;
91			goto invert;
92		}
93		n = 0;
94		goto done;
95 possible:
96		r = (l = buf + index) + exactlen;
97		while (l > beg)
98			if (*--l == sep)
99			{
100				l++;
101				break;
102			}
103		if ((r - l) < leftlen)
104			goto spanned;
105		while (r < end && *r != sep)
106			r++;
107		if ((r - (buf + index)) < rightlen)
108			goto spanned;
109		if (complete || (env->rex = ((r - l) > 128) ? e : e->next) && !(n = regnexec(p, (char*)l, r - l, nmatch, match, flags)))
110		{
111			if (inv)
112			{
113 invert:
114				x = beg;
115				while (beg < l)
116				{
117					while (x < l && *x != sep)
118						x++;
119					if (n = (*record)(handle, (char*)beg, x - beg))
120						goto done;
121					beg = ++x;
122				}
123			}
124			else if (n = (*record)(handle, (char*)l, r - l))
125				goto done;
126			if ((index = (r - buf) + leftlen) >= len)
127			{
128				n = (inv && (++r - buf) < len) ? (*record)(handle, (char*)r, (buf + len) - r): 0;
129				goto done;
130			}
131			beg = r + 1;
132		}
133		else if (n != REG_NOMATCH)
134			goto done;
135		else
136		{
137 spanned:
138			if ((index += exactlen) >= mid)
139				goto impossible;
140		}
141	}
142 done:
143	env->rex = e;
144	return n;
145}
146
147/*
148 * 20120528: regoff_t changed from int to ssize_t
149 */
150
151#if defined(__EXPORT__)
152#define extern		__EXPORT__
153#endif
154
155#undef	regrexec
156#if _map_libc
157#define regrexec	_ast_regrexec
158#endif
159
160extern int
161regrexec(const regex_t* p, const char* s, size_t len, size_t nmatch, oldregmatch_t* oldmatch, regflags_t flags, int sep, void* handle, regrecord_t record)
162{
163	if (oldmatch)
164	{
165		regmatch_t*	match;
166		ssize_t		i;
167		int		r;
168
169		if (!(match = oldof(0, regmatch_t, nmatch, 0)))
170			return -1;
171		if (!(r = regrexec_20120528(p, s, len, nmatch, match, flags, sep, handle, record)))
172			for (i = 0; i < nmatch; i++)
173			{
174				oldmatch[i].rm_so = match[i].rm_so;
175				oldmatch[i].rm_eo = match[i].rm_eo;
176			}
177		free(match);
178		return r;
179	}
180	return regrexec_20120528(p, s, len, 0, NiL, flags, sep, handle, record);
181}
182