1/***********************************************************************
2*                                                                      *
3*               This software is part of the ast package               *
4*          Copyright (c) 1985-2011 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 * Glenn Fowler
26 * AT&T Research
27 *
28 * return RE expression given strmatch() pattern
29 * 0 returned for invalid RE
30 */
31
32#include <ast.h>
33
34typedef struct Stack_s
35{
36	char*		beg;
37	short		len;
38	short		min;
39} Stack_t;
40
41char*
42fmtre(const char* as)
43{
44	register char*		s = (char*)as;
45	register int		c;
46	register char*		t;
47	register Stack_t*	p;
48	char*			x;
49	int			n;
50	int			end;
51	char*			buf;
52	Stack_t			stack[32];
53
54	end = 1;
55	c = 2 * strlen(s) + 1;
56	t = buf = fmtbuf(c);
57	p = stack;
58	if (*s != '*' || *(s + 1) == '(' || *(s + 1) == '-' && *(s + 2) == '(')
59		*t++ = '^';
60	else
61		s++;
62	for (;;)
63	{
64		switch (c = *s++)
65		{
66		case 0:
67			break;
68		case '\\':
69			if (!(c = *s++) || c == '{' || c == '}')
70				return 0;
71			*t++ = '\\';
72			if ((*t++ = c) == '(' && *s == '|')
73			{
74				*t++ = *s++;
75				goto logical;
76			}
77			continue;
78		case '[':
79			*t++ = c;
80			n = 0;
81			if ((c = *s++) == '!')
82			{
83				*t++ = '^';
84				c = *s++;
85			}
86			else if (c == '^')
87			{
88				if ((c = *s++) == ']')
89				{
90					*(t - 1) = '\\';
91					*t++ = '^';
92					continue;
93				}
94				n = '^';
95			}
96			for (;;)
97			{
98				if (!(*t++ = c))
99					return 0;
100				if ((c = *s++) == ']')
101				{
102					if (n)
103						*t++ = n;
104					*t++ = c;
105					break;
106				}
107			}
108			continue;
109		case '{':
110			for (x = s; *x && *x != '}'; x++);
111			if (*x++ && (*x == '(' || *x == '-' && *(x + 1) == '('))
112			{
113				if (p >= &stack[elementsof(stack)])
114					return 0;
115				p->beg = s - 1;
116				s = x;
117				p->len = s - p->beg;
118				if (p->min = *s == '-')
119					s++;
120				p++;
121				*t++ = *s++;
122			}
123			else
124				*t++ = c;
125			continue;
126		case '*':
127			if (!*s)
128			{
129				end = 0;
130				break;
131			}
132			/*FALLTHROUGH*/
133		case '?':
134		case '+':
135		case '@':
136		case '!':
137		case '~':
138			if (*s == '(' || c != '~' && *s == '-' && *(s + 1) == '(')
139			{
140				if (p >= &stack[elementsof(stack)])
141					return 0;
142				p->beg = s - 1;
143				if (c == '~')
144				{
145					if (*(s + 1) == 'E' && *(s + 2) == ')')
146					{
147						for (s += 3; *t = *s; t++, s++);
148						continue;
149					}
150					p->len = 0;
151					p->min = 0;
152					*t++ = *s++;
153					*t++ = '?';
154				}
155				else
156				{
157					p->len = c != '@';
158					if (p->min = *s == '-')
159						s++;
160					*t++ = *s++;
161				}
162				p++;
163			}
164			else
165			{
166				switch (c)
167				{
168				case '*':
169					*t++ = '.';
170					break;
171				case '?':
172					c = '.';
173					break;
174				case '+':
175				case '!':
176					*t++ = '\\';
177					break;
178				}
179				*t++ = c;
180			}
181			continue;
182		case '(':
183			if (p >= &stack[elementsof(stack)])
184				return 0;
185			p->beg = s - 1;
186			p->len = 0;
187			p->min = 0;
188			p++;
189			*t++ = c;
190			continue;
191		case ')':
192			if (p == stack)
193				return 0;
194			*t++ = c;
195			p--;
196			for (c = 0; c < p->len; c++)
197				*t++ = p->beg[c];
198			if (p->min)
199				*t++ = '?';
200			continue;
201		case '^':
202		case '.':
203		case '$':
204			*t++ = '\\';
205			*t++ = c;
206			continue;
207		case '|':
208			if (t == buf || *(t - 1) == '(')
209				return 0;
210		logical:
211			if (!*s || *s == ')')
212				return 0;
213			/*FALLTHROUGH*/
214		default:
215			*t++ = c;
216			continue;
217		}
218		break;
219	}
220	if (p != stack)
221		return 0;
222	if (end)
223		*t++ = '$';
224	*t = 0;
225	return buf;
226}
227