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