1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1985-2011 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12da2e3ebdSchin *                                                                      *
13da2e3ebdSchin *              Information and Software Systems Research               *
14da2e3ebdSchin *                            AT&T Research                             *
15da2e3ebdSchin *                           Florham Park NJ                            *
16da2e3ebdSchin *                                                                      *
17da2e3ebdSchin *                 Glenn Fowler <gsf@research.att.com>                  *
18da2e3ebdSchin *                  David Korn <dgk@research.att.com>                   *
19da2e3ebdSchin *                   Phong Vo <kpv@research.att.com>                    *
20da2e3ebdSchin *                                                                      *
21da2e3ebdSchin ***********************************************************************/
22da2e3ebdSchin #pragma prototyped
23da2e3ebdSchin /*
24da2e3ebdSchin  * Glenn Fowler
25da2e3ebdSchin  * AT&T Research
26da2e3ebdSchin  *
27da2e3ebdSchin  * return strmatch() expression given REG_AUGMENTED RE
28da2e3ebdSchin  * 0 returned for invalid RE
29da2e3ebdSchin  */
30da2e3ebdSchin 
31da2e3ebdSchin #include <ast.h>
32da2e3ebdSchin 
33da2e3ebdSchin char*
fmtmatch(const char * as)34da2e3ebdSchin fmtmatch(const char* as)
35da2e3ebdSchin {
36da2e3ebdSchin 	register char*	s = (char*)as;
37da2e3ebdSchin 	register int	c;
38da2e3ebdSchin 	register char*	t;
39da2e3ebdSchin 	register char**	p;
40da2e3ebdSchin 	register char*	b;
41da2e3ebdSchin 	char*		x;
42da2e3ebdSchin 	char*		y;
43da2e3ebdSchin 	char*		z;
44da2e3ebdSchin 	int		a;
45da2e3ebdSchin 	int		e;
46da2e3ebdSchin 	int		n;
47da2e3ebdSchin 	char*		buf;
48da2e3ebdSchin 	char*		stack[32];
49da2e3ebdSchin 
50da2e3ebdSchin 	c = 3 * (strlen(s) + 1);
51da2e3ebdSchin 	buf = fmtbuf(c);
52da2e3ebdSchin 	t = b = buf + 3;
53da2e3ebdSchin 	p = stack;
54da2e3ebdSchin 	if (a = *s == '^')
55da2e3ebdSchin 		s++;
56da2e3ebdSchin 	e = 0;
57da2e3ebdSchin 	for (;;)
58da2e3ebdSchin 	{
59da2e3ebdSchin 		switch (c = *s++)
60da2e3ebdSchin 		{
61da2e3ebdSchin 		case 0:
62da2e3ebdSchin 			break;
63da2e3ebdSchin 		case '\\':
64da2e3ebdSchin 			if (!(c = *s++))
65da2e3ebdSchin 				return 0;
66da2e3ebdSchin 			switch (*s)
67da2e3ebdSchin 			{
68da2e3ebdSchin 			case '*':
69da2e3ebdSchin 			case '+':
70da2e3ebdSchin 			case '?':
71da2e3ebdSchin 				*t++ = *s++;
72da2e3ebdSchin 				*t++ = '(';
73da2e3ebdSchin 				*t++ = '\\';
74da2e3ebdSchin 				*t++ = c;
75da2e3ebdSchin 				c = ')';
76da2e3ebdSchin 				break;
77da2e3ebdSchin 			case '|':
78da2e3ebdSchin 			case '&':
79da2e3ebdSchin 				if (c == '(')
80da2e3ebdSchin 				{
81da2e3ebdSchin 					*t++ = c;
82da2e3ebdSchin 					c = *s++;
83da2e3ebdSchin 					goto logical;
84da2e3ebdSchin 				}
85da2e3ebdSchin 				break;
86da2e3ebdSchin 			case '{':
87da2e3ebdSchin 			case '}':
88da2e3ebdSchin 				break;
89da2e3ebdSchin 			default:
90da2e3ebdSchin 				*t++ = '\\';
91da2e3ebdSchin 				break;
92da2e3ebdSchin 			}
93da2e3ebdSchin 			*t++ = c;
94da2e3ebdSchin 			continue;
95da2e3ebdSchin 		case '[':
96da2e3ebdSchin 			x = t;
97da2e3ebdSchin 			*t++ = c;
98da2e3ebdSchin 			if ((c = *s++) == '^')
99da2e3ebdSchin 			{
100da2e3ebdSchin 				*t++ = '!';
101da2e3ebdSchin 				c = *s++;
102da2e3ebdSchin 			}
103da2e3ebdSchin 			else if (c == '!')
104da2e3ebdSchin 			{
105da2e3ebdSchin 				*t++ = '\\';
106da2e3ebdSchin 				*t++ = c;
107da2e3ebdSchin 				c = *s++;
108da2e3ebdSchin 			}
109da2e3ebdSchin 			for (;;)
110da2e3ebdSchin 			{
111da2e3ebdSchin 				if (!(*t++ = c))
112da2e3ebdSchin 					return 0;
113da2e3ebdSchin 				if (c == '\\')
114da2e3ebdSchin 					*t++ = c;
115da2e3ebdSchin 				if ((c = *s++) == ']')
116da2e3ebdSchin 				{
117da2e3ebdSchin 					*t++ = c;
118da2e3ebdSchin 					break;
119da2e3ebdSchin 				}
120da2e3ebdSchin 			}
121da2e3ebdSchin 			switch (*s)
122da2e3ebdSchin 			{
123da2e3ebdSchin 			case '*':
124da2e3ebdSchin 			case '+':
125da2e3ebdSchin 			case '?':
126da2e3ebdSchin 				for (y = t + 2, t--; t >= x; t--)
127da2e3ebdSchin 					*(t + 2) = *t;
128da2e3ebdSchin 				*++t = *s++;
129da2e3ebdSchin 				*++t = '(';
130da2e3ebdSchin 				t = y;
131da2e3ebdSchin 				*t++ = ')';
132da2e3ebdSchin 				break;
133da2e3ebdSchin 			}
134da2e3ebdSchin 			continue;
135da2e3ebdSchin 		case '(':
136da2e3ebdSchin 			if (p >= &stack[elementsof(stack)])
137da2e3ebdSchin 				return 0;
138da2e3ebdSchin 			*p++ = t;
139da2e3ebdSchin 			if (*s == '?')
140da2e3ebdSchin 			{
141da2e3ebdSchin 				s++;
142da2e3ebdSchin 				if (*s == 'K' && *(s + 1) == ')')
143da2e3ebdSchin 				{
144da2e3ebdSchin 					s += 2;
145da2e3ebdSchin 					p--;
146da2e3ebdSchin 					while (*t = *s)
147da2e3ebdSchin 						t++, s++;
148da2e3ebdSchin 					continue;
149da2e3ebdSchin 				}
150da2e3ebdSchin 				*t++ = '~';
151da2e3ebdSchin 			}
152da2e3ebdSchin 			else
153da2e3ebdSchin 				*t++ = '@';
154da2e3ebdSchin 			*t++ = '(';
155da2e3ebdSchin 			continue;
156da2e3ebdSchin 		case ')':
157da2e3ebdSchin 			if (p == stack)
158da2e3ebdSchin 				return 0;
159da2e3ebdSchin 			p--;
160da2e3ebdSchin 			*t++ = c;
161da2e3ebdSchin 			switch (*s)
162da2e3ebdSchin 			{
163da2e3ebdSchin 			case 0:
164da2e3ebdSchin 				break;
165da2e3ebdSchin 			case '*':
166da2e3ebdSchin 			case '+':
167da2e3ebdSchin 			case '?':
168da2e3ebdSchin 			case '!':
169da2e3ebdSchin 				**p = *s++;
170da2e3ebdSchin 				if (*s == '?')
171da2e3ebdSchin 				{
172da2e3ebdSchin 					s++;
173da2e3ebdSchin 					x = *p + 1;
174da2e3ebdSchin 					for (y = ++t; y > x; y--)
175da2e3ebdSchin 						*y = *(y - 1);
176da2e3ebdSchin 					*x = '-';
177da2e3ebdSchin 				}
178da2e3ebdSchin 				continue;
179da2e3ebdSchin 			case '{':
180da2e3ebdSchin 				for (z = s; *z != '}'; z++)
181da2e3ebdSchin 					if (!*z)
182da2e3ebdSchin 						return 0;
183da2e3ebdSchin 				n = z - s;
184da2e3ebdSchin 				if (*++z == '?')
185da2e3ebdSchin 					n++;
186da2e3ebdSchin 				x = *p + n;
187da2e3ebdSchin 				for (y = t += n; y > x; y--)
188da2e3ebdSchin 					*y = *(y - n);
189da2e3ebdSchin 				for (x = *p; s < z; *x++ = *s++);
190da2e3ebdSchin 				if (*s == '?')
191da2e3ebdSchin 				{
192da2e3ebdSchin 					s++;
193da2e3ebdSchin 					*x++ = '-';
194da2e3ebdSchin 				}
195da2e3ebdSchin 				continue;
196da2e3ebdSchin 			default:
197da2e3ebdSchin 				continue;
198da2e3ebdSchin 			}
199da2e3ebdSchin 			break;
200da2e3ebdSchin 		case '.':
201da2e3ebdSchin 			switch (*s)
202da2e3ebdSchin 			{
203da2e3ebdSchin 			case 0:
204da2e3ebdSchin 				*t++ = '?';
205da2e3ebdSchin 				break;
206da2e3ebdSchin 			case '*':
207da2e3ebdSchin 				s++;
208da2e3ebdSchin 				*t++ = '*';
209da2e3ebdSchin 				e = !*s;
210da2e3ebdSchin 				continue;
211da2e3ebdSchin 			case '+':
212da2e3ebdSchin 				s++;
213da2e3ebdSchin 				*t++ = '?';
214da2e3ebdSchin 				*t++ = '*';
215da2e3ebdSchin 				continue;
216da2e3ebdSchin 			case '?':
217da2e3ebdSchin 				s++;
218da2e3ebdSchin 				*t++ = '?';
219da2e3ebdSchin 				*t++ = '(';
220da2e3ebdSchin 				*t++ = '?';
221da2e3ebdSchin 				*t++ = ')';
222da2e3ebdSchin 				continue;
223da2e3ebdSchin 			default:
224da2e3ebdSchin 				*t++ = '?';
225da2e3ebdSchin 				continue;
226da2e3ebdSchin 			}
227da2e3ebdSchin 			break;
228da2e3ebdSchin 		case '*':
229da2e3ebdSchin 		case '+':
230da2e3ebdSchin 		case '?':
231da2e3ebdSchin 		case '{':
232da2e3ebdSchin 			n = *(t - 1);
233da2e3ebdSchin 			if (t == b || n == '(' || n == '|')
234da2e3ebdSchin 				return 0;
235da2e3ebdSchin 			*(t - 1) = c;
236da2e3ebdSchin 			if (c == '{')
237da2e3ebdSchin 			{
238da2e3ebdSchin 				for (z = s; *z != '}'; z++)
239da2e3ebdSchin 					if (!*z)
240da2e3ebdSchin 						return 0;
241da2e3ebdSchin 				for (; s <= z; *t++ = *s++);
242da2e3ebdSchin 			}
243da2e3ebdSchin 			if (*s == '?')
244da2e3ebdSchin 			{
245da2e3ebdSchin 				s++;
246da2e3ebdSchin 				*t++ = '-';
247da2e3ebdSchin 			}
248da2e3ebdSchin 			*t++ = '(';
249da2e3ebdSchin 			*t++ = n;
250da2e3ebdSchin 			*t++ = ')';
251da2e3ebdSchin 			continue;
252da2e3ebdSchin 		case '|':
253da2e3ebdSchin 		case '&':
254da2e3ebdSchin 			if (t == b || *(t - 1) == '(')
255da2e3ebdSchin 				return 0;
256da2e3ebdSchin 		logical:
257da2e3ebdSchin 			if (!*s || *s == ')')
258da2e3ebdSchin 				return 0;
259da2e3ebdSchin 			if (p == stack && b == buf + 3)
260da2e3ebdSchin 			{
261da2e3ebdSchin 				*--b = '(';
262da2e3ebdSchin 				*--b = '@';
263da2e3ebdSchin 			}
264da2e3ebdSchin 			*t++ = c;
265da2e3ebdSchin 			continue;
266da2e3ebdSchin 		case '$':
267da2e3ebdSchin 			if (e = !*s)
268da2e3ebdSchin 				break;
269da2e3ebdSchin 			/*FALLTHROUGH*/
270da2e3ebdSchin 		default:
271da2e3ebdSchin 			*t++ = c;
272da2e3ebdSchin 			continue;
273da2e3ebdSchin 		}
274da2e3ebdSchin 		break;
275da2e3ebdSchin 	}
276da2e3ebdSchin 	if (p != stack)
277da2e3ebdSchin 		return 0;
278da2e3ebdSchin 	if (b != buf + 3)
279da2e3ebdSchin 		*t++ = ')';
280da2e3ebdSchin 	if (!a && (*b != '*' || *(b + 1) == '(' || (*(b + 1) == '-' || *(b + 1) == '~') && *(b + 2) == '('))
281da2e3ebdSchin 		*--b = '*';
282da2e3ebdSchin 	if (!e)
283da2e3ebdSchin 		*t++ = '*';
284da2e3ebdSchin 	*t = 0;
285da2e3ebdSchin 	return b;
286da2e3ebdSchin }
287