/*	Copyright (c) 1988 AT&T	*/
/*	  All Rights Reserved  	*/

/*	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T	*/
/*	The copyright notice above does not evidence any   	*/
/*	actual or intended publication of such source code.	*/

/*
 *      Copyright (c) 1997, by Sun Microsystems, Inc.
 *      All rights reserved.
 */

#pragma ident	"@(#)regcmp.c	1.5	97/09/17 SMI"	/* SVr4.0 1.2	*/

/*LINTLIBRARY*/

#include <sys/types.h>
#include <stdlib.h>
#include "utility.h"

/* this code was taken from REGCMP(3X) */

#define	SSIZE	50
#define	TGRP	48
#define	A256	02
#define	ZERO	01
#define	NBRA	10
#define	CIRCFL	32;
#define	SLOP	5
#define	FEOF	0 /* This was originally EOF but it clashes with the header */
			/* definition so it was changed to FEOF */

#define	CBRA	60
#define	GRP	40
#define	SGRP	56
#define	PGRP	68
#define	EGRP	44
#define	RNGE	03
#define	CCHR	20
#define	CDOT	64
#define	CCL	24
#define	NCCL	8
#define	CDOL	28
#define	FCEOF	52 /* This was originally CEOF but it clashes with the header */
			/* definition so it was changed to FCEOF */
#define	CKET	12

#define	STAR	01
#define	PLUS	02
#define	MINUS	16


int	*__sp_;
char	*__stmax;
int	__i_size;

char *
regcmp_p2(char *cs1, char *cs2)
{
	return (regcmp(cs1, cs2, (char *) NULL, (char *) NULL,
		(char *) NULL, (char *) NULL, (char *) NULL,
		(char *) NULL, (char *) NULL, (char *) NULL));
}

/*ARGSUSED2*/
char *
regcmp(char *cs1, char *cs2, char *cs3, char *cs4, char *cs5,
	char *cs6, char *cs7, char *cs8, char *cs9, char *cs10)
{
	char c;
	char *ep, *sp;
	int *adx;
	int i, cflg;
	char *lastep, *sep, *eptr;
	int nbra, ngrp;
	int cclcnt;
	char stack[SSIZE];

	__sp_ = (int *)stack;
	*__sp_ = -1;
	__stmax = &stack[SSIZE];

	adx = (int *)&cs1;
	i = nbra = ngrp = 0;
	while (*adx)
		i += __size((char *)*adx++);
	adx = (int *)&cs1;
	sp = (char *)*adx++;
	if ((sep = ep = malloc((unsigned)(2 * i + SLOP))) == NULL)
		return (NULL);
	if ((c = *sp++) == FEOF)
		goto cerror;
	if (c == '^') {
		c = *sp++;
		*ep++ = CIRCFL;
	}
	if ((c == '*') || (c == '+') || (c == '{'))
		goto cerror;
	sp--;
	for (;;) {
		if ((c = *sp++) == FEOF) {
			if (*adx) {
				sp = (char *)*adx++;
				continue;
			}
			*ep++ = FCEOF;
			if (--nbra > NBRA || *__sp_ != -1)
				goto cerror;
			__i_size = (int) (ep - sep);
			return (sep);
		}
		if ((c != '*') && (c != '{') && (c != '+'))
			lastep = ep;
		switch (c) {

		case '(':
			if (!__rpush(ep)) goto cerror;
			*ep++ = CBRA;
			*ep++ = -1;
			continue;
		case ')':
			if (!(eptr = (char *)__rpop())) goto cerror;
			if ((c = *sp++) == '$') {
				if ('0' > (c = *sp++) || c > '9')
					goto cerror;
				*ep++ = CKET;
				*ep++ = *++eptr = nbra++;
				*ep++ = (c-'0');
				continue;
			}
			*ep++ = EGRP;
			*ep++ = ngrp++;
			sp--;
			switch (c) {
			case '+':
				*eptr = PGRP;
				break;
			case '*':
				*eptr = SGRP;
				break;
			case '{':
				*eptr = TGRP;
				break;
			default:
				*eptr = GRP;
				continue;
			}
			i = (int) (ep - eptr - 2);
			for (cclcnt = 0; i >= 256; cclcnt++)
				i -= 256;
			if (cclcnt > 3) goto cerror;
			*eptr |= cclcnt;
			*++eptr = (char) i;
			continue;

		case '\\':
			*ep++ = CCHR;
			if ((c = *sp++) == FEOF)
				goto cerror;
			*ep++ = c;
			continue;

		case '{':
			*lastep |= RNGE;
			cflg = 0;
		nlim:
			if ((c = *sp++) == '}') goto cerror;
			i = 0;
			do {
				if ('0' <= c && c <= '9')
					i = (i*10+(c-'0'));
				else goto cerror;
			} while (((c = *sp++) != '}') && (c != ','));
			if (i > 255) goto cerror;
			*ep++ = (char) i;
			if (c == ',') {
				if (cflg++) goto cerror;
				if ((c = *sp++) == '}') {
					*ep++ = -1;
					continue;
				} else {
					sp--;
					goto nlim;
				}
			}
			if (!cflg)
				*ep++ = (char) i;
			else if ((ep[-1]&0377) < (ep[-2]&0377))
				goto cerror;
			continue;

		case '.':
			*ep++ = CDOT;
			continue;

		case '+':
			if (*lastep == CBRA || *lastep == CKET)
				goto cerror;
			*lastep |= PLUS;
			continue;

		case '*':
			if (*lastep == CBRA || *lastep == CKET)
			goto cerror;
			*lastep |= STAR;
			continue;

		case '$':
			if ((*sp != FEOF) || (*adx))
				goto defchar;
			*ep++ = CDOL;
			continue;

		case '[':
			*ep++ = CCL;
			*ep++ = 0;
			cclcnt = 1;
			if ((c = *sp++) == '^') {
				c = *sp++;
				ep[-2] = NCCL;
			}
			do {
				if (c == FEOF)
					goto cerror;
				if ((c == '-') && (cclcnt > 1) &&
				    (*sp != ']')) {
					*ep++ = ep[-1];
					ep[-2] = MINUS;
					cclcnt++;
					continue;
				}
				*ep++ = c;
				cclcnt++;
			} while ((c = *sp++) != ']');
			lastep[1] = (char) cclcnt;
			continue;

		defchar:
		default:
			*ep++ = CCHR;
			*ep++ = c;
		}
	}
cerror:
	free(sep);
	return (0);
}

int
__size(char *strg)
{
	int	i;

	i = 1;
	while (*strg++)
		i++;
	return (i);
}

int
__rpop(void)
{
	return ((*__sp_ == -1)?0:*__sp_--);
}

int
__rpush(char *ptr)
{
	if (++__sp_ > (int *)__stmax)
		return (0);
	*__sp_ = (int)ptr;
	return (1);
}
