xref: /illumos-gate/usr/src/lib/libeti/form/common/regcmp.c (revision dd72704bd9e794056c558153663c739e2012d721)
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 #include <sys/types.h>
36 #include <stdlib.h>
37 #include "utility.h"
38 
39 /* this code was taken from regcmp(3C) */
40 
41 #define	SSIZE	16
42 #define	TGRP	48
43 #define	A256	02
44 #define	ZERO	01
45 #define	NBRA	10
46 #define	CIRCFL	32;
47 #define	SLOP	5
48 #define	FEOF	0 /* This was originally EOF but it clashes with the header */
49 			/* definition so it was changed to FEOF */
50 
51 #define	CBRA	60
52 #define	GRP	40
53 #define	SGRP	56
54 #define	PGRP	68
55 #define	EGRP	44
56 #define	RNGE	03
57 #define	CCHR	20
58 #define	CDOT	64
59 #define	CCL	24
60 #define	NCCL	8
61 #define	CDOL	28
62 #define	FCEOF	52 /* This was originally CEOF but it clashes with the header */
63 			/* definition so it was changed to FCEOF */
64 #define	CKET	12
65 
66 #define	STAR	01
67 #define	PLUS	02
68 #define	MINUS	16
69 
70 intptr_t	*__sp_;
71 intptr_t	*__stmax;
72 extern int	__i_size;
73 
74 /*ARGSUSED2*/
75 char *
76 libform_regcmp(char *cs1, char *cs2)
77 {
78 	char c;
79 	char *ep, *sp;
80 	int *adx;
81 	int i, cflg;
82 	char *lastep, *sep, *eptr;
83 	int nbra, ngrp;
84 	int cclcnt;
85 	intptr_t stack[SSIZE];
86 
87 	__sp_ = stack;
88 	*__sp_ = -1;
89 	__stmax = &stack[SSIZE];
90 
91 	adx = (int *)&cs1;
92 	i = nbra = ngrp = 0;
93 	while (*adx)
94 		i += __size((char *)(intptr_t)*adx++);
95 	adx = (int *)&cs1;
96 	sp = (char *)(intptr_t)*adx++;
97 	if ((sep = ep = malloc((unsigned)(2 * i + SLOP))) == NULL)
98 		return (NULL);
99 	if ((c = *sp++) == FEOF)
100 		goto cerror;
101 	if (c == '^') {
102 		c = *sp++;
103 		*ep++ = CIRCFL;
104 	}
105 	if ((c == '*') || (c == '+') || (c == '{'))
106 		goto cerror;
107 	sp--;
108 	for (;;) {
109 		if ((c = *sp++) == FEOF) {
110 			if (*adx) {
111 				sp = (char *)(intptr_t)*adx++;
112 				continue;
113 			}
114 			*ep++ = FCEOF;
115 			if (--nbra > NBRA || *__sp_ != -1)
116 				goto cerror;
117 			__i_size = (int)(ep - sep);
118 			return (sep);
119 		}
120 		if ((c != '*') && (c != '{') && (c != '+'))
121 			lastep = ep;
122 		switch (c) {
123 
124 		case '(':
125 			if (!__rpush(ep)) goto cerror;
126 			*ep++ = CBRA;
127 			*ep++ = -1;
128 			continue;
129 		case ')':
130 			if (!(eptr = (char *)__rpop())) goto cerror;
131 			if ((c = *sp++) == '$') {
132 				if ('0' > (c = *sp++) || c > '9')
133 					goto cerror;
134 				*ep++ = CKET;
135 				*ep++ = *++eptr = nbra++;
136 				*ep++ = (c-'0');
137 				continue;
138 			}
139 			*ep++ = EGRP;
140 			*ep++ = ngrp++;
141 			sp--;
142 			switch (c) {
143 			case '+':
144 				*eptr = PGRP;
145 				break;
146 			case '*':
147 				*eptr = SGRP;
148 				break;
149 			case '{':
150 				*eptr = TGRP;
151 				break;
152 			default:
153 				*eptr = GRP;
154 				continue;
155 			}
156 			i = (int)(ep - eptr - 2);
157 			for (cclcnt = 0; i >= 256; cclcnt++)
158 				i -= 256;
159 			if (cclcnt > 3) goto cerror;
160 			*eptr |= cclcnt;
161 			*++eptr = (char)i;
162 			continue;
163 
164 		case '\\':
165 			*ep++ = CCHR;
166 			if ((c = *sp++) == FEOF)
167 				goto cerror;
168 			*ep++ = c;
169 			continue;
170 
171 		case '{':
172 			*lastep |= RNGE;
173 			cflg = 0;
174 		nlim:
175 			if ((c = *sp++) == '}') goto cerror;
176 			i = 0;
177 			do {
178 				if ('0' <= c && c <= '9')
179 					i = (i*10+(c-'0'));
180 				else goto cerror;
181 			} while (((c = *sp++) != '}') && (c != ','));
182 			if (i > 255) goto cerror;
183 			*ep++ = (char)i;
184 			if (c == ',') {
185 				if (cflg++) goto cerror;
186 				if ((c = *sp++) == '}') {
187 					*ep++ = -1;
188 					continue;
189 				} else {
190 					sp--;
191 					goto nlim;
192 				}
193 			}
194 			if (!cflg)
195 				*ep++ = (char)i;
196 			else if ((ep[-1]&0377) < (ep[-2]&0377))
197 				goto cerror;
198 			continue;
199 
200 		case '.':
201 			*ep++ = CDOT;
202 			continue;
203 
204 		case '+':
205 			if (*lastep == CBRA || *lastep == CKET)
206 				goto cerror;
207 			*lastep |= PLUS;
208 			continue;
209 
210 		case '*':
211 			if (*lastep == CBRA || *lastep == CKET)
212 				goto cerror;
213 			*lastep |= STAR;
214 			continue;
215 
216 		case '$':
217 			if ((*sp != FEOF) || (*adx))
218 				goto defchar;
219 			*ep++ = CDOL;
220 			continue;
221 
222 		case '[':
223 			*ep++ = CCL;
224 			*ep++ = 0;
225 			cclcnt = 1;
226 			if ((c = *sp++) == '^') {
227 				c = *sp++;
228 				ep[-2] = NCCL;
229 			}
230 			do {
231 				if (c == FEOF)
232 					goto cerror;
233 				if ((c == '-') && (cclcnt > 1) &&
234 				    (*sp != ']')) {
235 					*ep = ep[-1];
236 					ep++;
237 					ep[-2] = MINUS;
238 					cclcnt++;
239 					continue;
240 				}
241 				*ep++ = c;
242 				cclcnt++;
243 			} while ((c = *sp++) != ']');
244 			lastep[1] = (char)cclcnt;
245 			continue;
246 
247 		defchar:
248 		default:
249 			*ep++ = CCHR;
250 			*ep++ = c;
251 		}
252 	}
253 cerror:
254 	free(sep);
255 	return (0);
256 }
257 
258 int
259 __size(char *strg)
260 {
261 	int	i;
262 
263 	i = 1;
264 	while (*strg++)
265 		i++;
266 	return (i);
267 }
268 
269 intptr_t
270 __rpop(void)
271 {
272 	return ((*__sp_ == -1)?0:*__sp_--);
273 }
274 
275 int
276 __rpush(char *ptr)
277 {
278 	if (__sp_ >= __stmax)
279 		return (0);
280 	*++__sp_ = (intptr_t)ptr;
281 	return (1);
282 }
283