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