xref: /illumos-gate/usr/src/lib/libeti/form/common/regex.c (revision 8a2b682e57a046b828f37bcde1776f131ef4629f)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*	Copyright (c) 1988 AT&T	*/
23 /*	  All Rights Reserved  	*/
24 
25 
26 /*
27  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
28  * Use is subject to license terms.
29  */
30 
31 /*
32  * Copyright (c) 2018, Joyent, Inc.
33  */
34 
35 /*LINTLIBRARY*/
36 
37 #include <sys/types.h>
38 #include <stdlib.h>
39 #include <unistd.h>
40 #include "utility.h"
41 
42 /*
43  *	this code was taken from REGCMP(3X)
44  */
45 /*VARARGS*/
46 /*ARGSUSED*/
47 
48 #define	SSIZE	50
49 #define	TGRP	48
50 #define	A256	01
51 #define	A512	02
52 #define	A768	03
53 #define	NBRA	10
54 #define	CIRCFL	32
55 
56 #define	CBRA	60
57 #define	GRP	40
58 #define	SGRP	56
59 #define	PGRP	68
60 #define	EGRP	44
61 #define	RNGE	03
62 #define	CCHR	20
63 #define	CDOT	64
64 #define	CCL	24
65 #define	NCCL	8
66 #define	CDOL	28
67 #define	FCEOF	52 /* This was originally CEOF but it clashes with the header */
68 			/* definition so it was changed to FCEOF */
69 #define	CKET	12
70 
71 #define	STAR	01
72 #define	PLUS	02
73 #define	MINUS	16
74 
75 char	*__braslist[NBRA];
76 char	*__braelist[NBRA];
77 char	*__loc1;
78 intptr_t	__bravar[NBRA];
79 intptr_t	*__st[SSIZE + 1];
80 intptr_t	*__eptr_, *__lptr_;
81 intptr_t	__cflg;
82 
83 char *
84 libform_regex(char *addrc, char *addrl, char *a1)
85 {
86 	intptr_t cur, in;
87 	intptr_t *adx;
88 	char *p1, *p2;
89 
90 	for (in = 0; in < NBRA; in++) {
91 		__braslist[in] = 0;
92 		__bravar[in] = -1;
93 	}
94 	__cflg = 0;
95 	cur = __execute(addrc, addrl);
96 	adx = (intptr_t *)&a1;
97 	for (in = 0; in < NBRA; in++) {
98 		if (((p1 = __braslist[in]) != 0) && (__bravar[in] >= 0)) {
99 			p2 = (char *)adx[__bravar[in]];
100 			while (p1 < __braelist[in]) *p2++ = *p1++;
101 			*p2 = '\0';
102 		}
103 	}
104 	if (!__cflg)
105 		return ((addrl == (char *)cur) ? (char *)0 : (char *)cur);
106 	else
107 		return ((char *)cur);
108 }
109 
110 intptr_t
111 __execute(char *addrc, char *addrl)
112 {
113 	char *p1, *p2, c;
114 	intptr_t i;
115 
116 	p1 = addrl;
117 	p2 = addrc;
118 	__eptr_ = (intptr_t *)&__st[SSIZE];
119 	__lptr_ = (intptr_t *)&__st[0];
120 	if (*p2 == CIRCFL) {
121 		__loc1 = p1;
122 		return ((i = __advance(p1, ++p2)) ? i : (intptr_t)addrl);
123 	}
124 	/* fast check for first character */
125 	if (*p2 == CCHR) {
126 		c = p2[1];
127 		do {
128 			if (*p1 != c)
129 				continue;
130 			__eptr_ = (intptr_t *)&__st[SSIZE];
131 			__lptr_ = (intptr_t *)&__st[0];
132 			if (i = __advance(p1, p2))  {
133 				__loc1 = p1;
134 				return (i);
135 			}
136 		} while (*p1++);
137 		return ((intptr_t)addrl);
138 	}
139 	/* regular algorithm */
140 	do {
141 		__eptr_ = (intptr_t *)&__st[SSIZE];
142 		__lptr_ = (intptr_t *)&__st[0];
143 		if (i = __advance(p1, p2))  {
144 			__loc1 = p1;
145 			return (i);
146 		}
147 	} while (*p1++);
148 	return ((intptr_t)addrl);
149 }
150 
151 intptr_t
152 __advance(char *alp, char *aep)
153 {
154 	char *lp, *ep, *curlp;
155 	char *sep, *dp;
156 	intptr_t i, lcnt, dcnt, gflg;
157 
158 	lp = alp;
159 	ep = aep;
160 	gflg = 0;
161 	for (; ; ) {
162 		switch (*ep++) {
163 
164 	case CCHR:
165 		if (*ep++ == *lp++)
166 			continue;
167 		return (0);
168 
169 	case EGRP|RNGE:
170 		return ((intptr_t)lp);
171 	case EGRP:
172 	case GRP:
173 		ep++;
174 		continue;
175 
176 	case EGRP|STAR:
177 		(void) __xpop(0);
178 		/* FALLTHROUGH */
179 	case EGRP|PLUS:
180 		(void) __xpush(0, ++ep);
181 		return ((intptr_t)lp);
182 
183 	case CDOT:
184 		if (*lp++)
185 			continue;
186 		return (0);
187 
188 	case CDOL:
189 		if (*lp == 0)
190 			continue;
191 		lp++;
192 		return (0);
193 
194 	case FCEOF:
195 		__cflg = 1;
196 		return ((intptr_t)lp);
197 
198 	case TGRP:
199 	case TGRP|A768:
200 	case TGRP|A512:
201 	case TGRP|A256:
202 		i = (((ep[-1] & 03) << 8) + (*ep) & 0377);
203 		ep++;
204 		(void) __xpush(0, ep + i + 2);
205 		(void) __xpush(0, ++ep);
206 		(void) __xpush(0, ++ep);
207 		gflg = 1;
208 		(void) __getrnge(&lcnt, &dcnt, &ep[i]);
209 		while (lcnt--)
210 			if (!(lp = (char *)__advance(lp, ep)))
211 				return (0);
212 		(void) __xpush(1, curlp = lp);
213 		while (dcnt--)
214 			if (!(dp = (char *)__advance(lp, ep))) break;
215 			else
216 				(void) __xpush(1, lp = dp);
217 		ep = (char *)__xpop(0);
218 		goto star;
219 	case CCHR|RNGE:
220 		sep = ep++;
221 		(void) __getrnge(&lcnt, &dcnt, ep);
222 		while (lcnt--)
223 			if (*lp++ != *sep)
224 				return (0);
225 		curlp = lp;
226 		while (dcnt--)
227 			if (*lp++ != *sep) break;
228 		if (dcnt < 0) lp++;
229 		ep += 2;
230 		goto star;
231 	case CDOT|RNGE:
232 		(void) __getrnge(&lcnt, &dcnt, ep);
233 		while (lcnt--)
234 			if (*lp++ == '\0')
235 				return (0);
236 		curlp = lp;
237 		while (dcnt--)
238 			if (*lp++ == '\0') break;
239 		if (dcnt < 0) lp++;
240 		ep += 2;
241 		goto star;
242 	case CCL|RNGE:
243 	case NCCL|RNGE:
244 		(void) __getrnge(&lcnt, &dcnt, (ep + (*ep & 0377)));
245 		while (lcnt--)
246 			if (!__cclass(ep, *lp++, ep[-1] == (CCL | RNGE)))
247 				return (0);
248 		curlp = lp;
249 		while (dcnt--)
250 			if (!__cclass(ep, *lp++, ep[-1] == (CCL|RNGE)))
251 				break;
252 		if (dcnt < 0) lp++;
253 		ep += (*ep + 2);
254 		goto star;
255 	case CCL:
256 		if (__cclass(ep, *lp++, 1)) {
257 			ep += *ep;
258 			continue;
259 		}
260 		return (0);
261 
262 	case NCCL:
263 		if (__cclass(ep, *lp++, 0)) {
264 			ep += *ep;
265 			continue;
266 		}
267 		return (0);
268 
269 	case CBRA:
270 		__braslist[*ep++] = lp;
271 		continue;
272 
273 	case CKET:
274 		__braelist[*ep] = lp;
275 		__bravar[*ep] = ep[1];
276 		ep += 2;
277 		continue;
278 
279 	case CDOT|PLUS:
280 		if (*lp++ == '\0')
281 			return (0);
282 		/* FALLTHROUGH */
283 	case CDOT|STAR:
284 		curlp = lp;
285 		while (*lp++)
286 			;
287 		goto star;
288 
289 	case CCHR|PLUS:
290 		if (*lp++ != *ep)
291 			return (0);
292 		/* FALLTHROUGH */
293 	case CCHR|STAR:
294 		curlp = lp;
295 		while (*lp++ == *ep)
296 			;
297 		ep++;
298 		goto star;
299 
300 	case PGRP:
301 	case PGRP|A256:
302 	case PGRP|A512:
303 	case PGRP|A768:
304 		if (!(lp = (char *)__advance(lp, ep+1)))
305 			return (0);
306 		/* FALLTHROUGH */
307 	case SGRP|A768:
308 	case SGRP|A512:
309 	case SGRP|A256:
310 	case SGRP:
311 		i = (((ep[-1]&03) << 8) + (*ep & 0377));
312 		ep++;
313 		(void) __xpush(0, ep + i);
314 		(void) __xpush(1, curlp = lp);
315 		while (i = __advance(lp, ep))
316 			(void) __xpush(1, lp = (char *)i);
317 		ep = (char *)__xpop(0);
318 		gflg = 1;
319 		goto star;
320 
321 	case CCL|PLUS:
322 	case NCCL|PLUS:
323 		if (!__cclass(ep, *lp++, ep[-1] == (CCL | PLUS)))
324 			return (0);
325 		/* FALLTHROUGH */
326 	case CCL|STAR:
327 	case NCCL|STAR:
328 		curlp = lp;
329 		while (__cclass(ep, *lp++, ((ep[-1] == (CCL | STAR)) ||
330 		    (ep[-1] == (CCL | PLUS)))))
331 			;
332 		ep += *ep;
333 		goto star;
334 
335 	star:
336 		do {
337 			if (!gflg) lp--;
338 			else if (!(lp = (char *)__xpop(1))) break;
339 			if (i = __advance(lp, ep))
340 				return (i);
341 		} while (lp > curlp);
342 		return (0);
343 
344 	default:
345 		return (0);
346 	}
347 	}
348 }
349 
350 intptr_t
351 __cclass(char *aset, char ac, intptr_t af)
352 {
353 	char *set, c;
354 	intptr_t n;
355 
356 	set = (char *)aset;
357 	if ((c = ac) == 0)
358 		return (0);
359 	n = *set++;
360 	while (--n) {
361 		if (*set == MINUS) {
362 			if ((set[2] - set[1]) < 0)
363 				return (0);
364 			if (*++set <= c) {
365 				if (c <= *++set)
366 					return (af);
367 			} else
368 				++set;
369 			++set;
370 			n -= 2;
371 			continue;
372 		}
373 		if (*set++ == c)
374 			return (af);
375 	}
376 	return (!af);
377 }
378 
379 intptr_t
380 __xpush(intptr_t i, char *p)
381 {
382 	if (__lptr_ >= __eptr_) {
383 		(void) write(2, "stack overflow\n", 15);
384 		(void) exit(1);
385 	}
386 	if (i)
387 		*__lptr_++ = (intptr_t)p;
388 	else
389 		*__eptr_-- = (intptr_t)p;
390 	return (1);
391 }
392 
393 intptr_t
394 __xpop(intptr_t i)
395 {
396 	if (i)
397 		return ((__lptr_ < (intptr_t *)&__st[0]) ? 0 : *--__lptr_);
398 	else
399 		return ((__eptr_ > (intptr_t *)&__st[SSIZE]) ? 0 : *++__eptr_);
400 }
401 
402 intptr_t
403 __getrnge(intptr_t *i, intptr_t *j, char *k)
404 {
405 	*i = (*k++&0377);
406 	if (*k == (char)-1)
407 		*j = 20000;
408 	else
409 		*j = ((*k&0377) - *i);
410 	return (1);
411 }
412