xref: /titanic_51/usr/src/lib/libast/common/string/fmtre.c (revision 853389e344087efe23a5cc688693e5301a1cb90d)
1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *           Copyright (c) 1985-2007 AT&T Knowledge Ventures            *
5 *                      and is licensed under the                       *
6 *                  Common Public License, Version 1.0                  *
7 *                      by AT&T Knowledge Ventures                      *
8 *                                                                      *
9 *                A copy of the License is available at                 *
10 *            http://www.opensource.org/licenses/cpl1.0.txt             *
11 *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
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 					*t++ = *s++;
152 					*t++ = '?';
153 				}
154 				else
155 				{
156 					p->len = c != '@';
157 					if (p->min = *s == '-')
158 						s++;
159 					*t++ = *s++;
160 				}
161 				p++;
162 			}
163 			else
164 			{
165 				switch (c)
166 				{
167 				case '*':
168 					*t++ = '.';
169 					break;
170 				case '?':
171 					c = '.';
172 					break;
173 				case '+':
174 				case '!':
175 					*t++ = '\\';
176 					break;
177 				}
178 				*t++ = c;
179 			}
180 			continue;
181 		case '(':
182 			if (p >= &stack[elementsof(stack)])
183 				return 0;
184 			p->beg = s - 1;
185 			p->len = 0;
186 			p->min = 0;
187 			p++;
188 			*t++ = c;
189 			continue;
190 		case ')':
191 			if (p == stack)
192 				return 0;
193 			*t++ = c;
194 			p--;
195 			for (c = 0; c < p->len; c++)
196 				*t++ = p->beg[c];
197 			if (p->min)
198 				*t++ = '?';
199 			continue;
200 		case '^':
201 		case '.':
202 		case '$':
203 			*t++ = '\\';
204 			*t++ = c;
205 			continue;
206 		case '|':
207 			if (t == buf || *(t - 1) == '(')
208 				return 0;
209 		logical:
210 			if (!*s || *s == ')')
211 				return 0;
212 			/*FALLTHROUGH*/
213 		default:
214 			*t++ = c;
215 			continue;
216 		}
217 		break;
218 	}
219 	if (p != stack)
220 		return 0;
221 	if (end)
222 		*t++ = '$';
223 	*t = 0;
224 	return buf;
225 }
226