xref: /illumos-gate/usr/src/contrib/ast/src/lib/libast/string/fmtre.c (revision 9b9d39d2a32ff806d2431dbcc50968ef1e6d46b2)
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 
34 typedef struct Stack_s
35 {
36 	char*		beg;
37 	short		len;
38 	short		min;
39 } Stack_t;
40 
41 char*
42 fmtre(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