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
72intptr_t	*__sp_;
73intptr_t	*__stmax;
74int	__i_size;
75
76/*ARGSUSED2*/
77char *
78libform_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	}
255cerror:
256	free(sep);
257	return (0);
258}
259
260int
261__size(char *strg)
262{
263	int	i;
264
265	i = 1;
266	while (*strg++)
267		i++;
268	return (i);
269}
270
271intptr_t
272__rpop(void)
273{
274	return ((*__sp_ == -1)?0:*__sp_--);
275}
276
277int
278__rpush(char *ptr)
279{
280	if (__sp_ >= __stmax)
281		return (0);
282	*++__sp_ = (intptr_t)ptr;
283	return (1);
284}
285